package com.mzj.saas.mservice.propertybill.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.mzj.saas.commons.ApiData;
import com.mzj.saas.commons.ResultBean;
import com.mzj.saas.commons.StatusCode;
import com.mzj.saas.commons.enums.BacklogItemTypeEnum;
import com.mzj.saas.commons.enums.PaymentCauseEnum;
import com.mzj.saas.commons.enums.PaymentTypeEnum;
import com.mzj.saas.commons.enums.RemainingStatusEnum;
import com.mzj.saas.commons.util.BeanUtils;
import com.mzj.saas.commons.util.ConvertUtils;
import com.mzj.saas.commons.util.DateUtils;
import com.mzj.saas.commons.util.StringUtils;
import com.mzj.saas.commons.vo.redis.TokenRedisVo;
import com.mzj.saas.config.pay.PayConfig;
import com.mzj.saas.config.sms.SmsConfig;
import com.mzj.saas.mservice.aio.vo.BillVO;
import com.mzj.saas.mservice.backlog.entity.BacklogItem;
import com.mzj.saas.mservice.backlog.entity.BacklogItemHouseRemaining;
import com.mzj.saas.mservice.backlog.entity.BacklogItemPropertyOtherBill;
import com.mzj.saas.mservice.backlog.entity.BacklogItemPropertyRentBill;
import com.mzj.saas.mservice.backlog.repository.BacklogItemHouseRemainingRepository;
import com.mzj.saas.mservice.backlog.repository.BacklogItemPropertyOtherBillRepository;
import com.mzj.saas.mservice.backlog.repository.BacklogItemPropertyRentBillRepository;
import com.mzj.saas.mservice.backlog.repository.BacklogItemRepository;
import com.mzj.saas.mservice.bill.entity.DepartmentBill;
import com.mzj.saas.mservice.bill.entity.HouseExpenseBillRule;
import com.mzj.saas.mservice.bill.entity.HouseWaitPaymentDetail;
import com.mzj.saas.mservice.bill.repository.DepartmentBillRepository;
import com.mzj.saas.mservice.bill.repository.HouseExpenseBillRuleRepository;
import com.mzj.saas.mservice.bill.repository.HouseWaitPaymentDetailRepository;
import com.mzj.saas.mservice.bill.vo.BillSearchRequestVO;
import com.mzj.saas.mservice.bill.vo.PaymentOrderApiData;
import com.mzj.saas.mservice.community.entity.Community;
import com.mzj.saas.mservice.community.entity.CommunityBuild;
import com.mzj.saas.mservice.community.entity.CommunityBuildUnit;
import com.mzj.saas.mservice.community.entity.HouseSurrender;
import com.mzj.saas.mservice.community.repository.CommunityBuildRepository;
import com.mzj.saas.mservice.community.repository.CommunityBuildUnitRepository;
import com.mzj.saas.mservice.community.repository.CommunityRepository;
import com.mzj.saas.mservice.community.repository.HouseSurrenderRepository;
import com.mzj.saas.mservice.community.service.AppCommunityService;
import com.mzj.saas.mservice.community.service.CommunityService;
import com.mzj.saas.mservice.department.entity.Department;
import com.mzj.saas.mservice.department.entity.UserDepartmentRef;
import com.mzj.saas.mservice.department.repository.DepartmentRepository;
import com.mzj.saas.mservice.department.repository.UserDepartmentRefRepository;
import com.mzj.saas.mservice.eligible.entity.DepartmentEnterpriseTagRef;
import com.mzj.saas.mservice.eligible.entity.DepartmentHierarchy;
import com.mzj.saas.mservice.eligible.repository.DepartmentEnterpriseTagRefRepository;
import com.mzj.saas.mservice.eligible.repository.DepartmentHierarchyRepository;
import com.mzj.saas.mservice.eligible.service.DepartmentHierarchyService;
import com.mzj.saas.mservice.house.entity.House;
import com.mzj.saas.mservice.house.repository.HouseRepository;
import com.mzj.saas.mservice.lock.Repository.HouseRemainingPostponeRepository;
import com.mzj.saas.mservice.lock.entity.HouseRemainingPostpone;
import com.mzj.saas.mservice.lock.service.LockAppService;
import com.mzj.saas.mservice.pay.service.WxPayService;
import com.mzj.saas.mservice.property.entity.*;
import com.mzj.saas.mservice.property.repository.*;
import com.mzj.saas.mservice.property.util.ObjectConversion;
import com.mzj.saas.mservice.property.vo.BillListVo;
import com.mzj.saas.mservice.property.vo.HouseRemainingRecordVo;
import com.mzj.saas.mservice.property.vo.ReturnDetailsVo;
import com.mzj.saas.mservice.propertybill.entity.*;
import com.mzj.saas.mservice.propertybill.repository.*;
import com.mzj.saas.mservice.propertybill.vo.*;
import com.mzj.saas.mservice.sms.service.SmsService;
import com.mzj.saas.mservice.sys.entity.AppUser;
import com.mzj.saas.mservice.sys.entity.User;
import com.mzj.saas.mservice.sys.repository.AppUserRepository;
import com.mzj.saas.mservice.sys.repository.UserRepository;
import com.mzj.saas.mservice.sys.repository.WechatAccountRepository;
import com.mzj.saas.mservice.sys.utils.SqlUtils;
import com.mzj.saas.redis.RedisService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AccountManageService {
    private static final Logger log = LoggerFactory.getLogger(AccountManageService.class);

    @Autowired
    private RedisService redisService;
    @Autowired
    private AppCommunityService appCommunityService;
    @Autowired
    private CommunityService communityService;
    @Autowired
    private PayConfig payConfig;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private CommunityRepository communityRepository;
    @Autowired
    private CommunityBuildRepository communityBuildRepository;
    @Autowired
    private CommunityBuildUnitRepository communityBuildUnitRepository;
    @Autowired
    private AppUserRepository appUserRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private EstateRentBillRepository estateRentBillRepository;
    @Autowired
    private EstateExpenseBillRepository estateExpenseBillRepository;
    @Autowired
    private DepartmentHierarchyService departmentHierarchyService;
    @Autowired
    private WechatAccountRepository wechatAccountRepository;
    @Autowired
    @Qualifier("stringRedisTemplate")
    private StringRedisTemplate redisTemplate;
    @Autowired
    private EstatePaymentOrderRelationRepository estatePaymentOrderRelationRepository;
    @Autowired
    private EstatePaymentOrderRepository estatePaymentOrderRepository;
    @Autowired
    private WithDrawService withDrawService;
    @Autowired
    private HouseRemainingRepository houseRemainingRepository;
    @Autowired
    private HouseRemainingRecordRepository houseRemainingRecordRepository;
    @Autowired
    private HouseRemainingRelationRepository houseRemainingRelationRepository;
    @Autowired
    private CommunityHouseUserRepository communityHouseUserRepository;
    @Autowired
    private BacklogItemPropertyOtherBillRepository backlogItemPropertyOtherBillRepository;
    @Autowired
    private BacklogItemRepository backlogItemRepository;
    @Autowired
    private BacklogItemHouseRemainingRepository backlogItemHouseRemainingRepository;
    @Autowired
    private BacklogItemPropertyRentBillRepository backlogItemPropertyRentBillRepository;
    @Autowired
    private HouseRepository houseRepository;
    @Autowired
    private HouseExpenseBillRuleRepository houseExpenseBillRuleRepository;
    @Autowired
    private SmsService smsService;
    @Autowired
    private SmsConfig smsConfig;
    @Autowired
    private EstateAdjustBillRepository estateAdjustBillRepository;
    @Autowired
    private HouseWaitPaymentDetailRepository houseWaitPaymentDetailRepository;
    @Autowired
    private EstateExpenseBillDetailRepository estateExpenseBillDetailRepository;
    @Autowired
    private DepartmentHierarchyRepository departmentHierarchyRepository;
    @Autowired
    private HouseOfflinePaymentDetailsRepository houseOfflinePaymentDetailsRepository;
    @Autowired
    private DepartmentAuditorRepository departmentAuditorRepository;
    @Autowired
    private UserDepartmentRefRepository userDepartmentRefRepository;
    @Autowired
    private DepartmentRepository departmentRepository;
    @Autowired
    private EstateViolateBillRepository estateViolateBillRepository;
    @Autowired
    private DepartmentEnterpriseTagRefRepository departmentEnterpriseTagRefRepository;
    @Autowired
    private HouseReturnBillRelationRepository houseReturnBillRelationRepository;
    @Autowired
    private HouseReturnPremiumRepository houseReturnPremiumRepository;
    @Autowired
    private HouseRemainingPostponeRepository houseRemainingPostponeRepository;
    @Autowired
    private DepartmentRemainingRepository departmentRemainingRepository;
    @Autowired
    private DepartmentRemainingRefRepository departmentRemainingRefRepository;
    @Autowired
    private DepartmentRemainingRecordRepository departmentRemainingRecordRepository;
    @Autowired
    private MatchUserHouseRepository matchUserHouseRepository;
    @Autowired
    private MatchUserRepository matchUserRepository;
    @Autowired
    private HouseSurrenderRepository houseSurrenderRepository;
    @Autowired
    private LockAppService lockAppService;
    @Autowired
    private DepartmentBillRepository departmentBillRepository;
    @Autowired
    private WxPayService wxPayService;


    private static final String SQL_PAGE = " LIMIT ? OFFSET ?";

    /**
     * 首页数据
     *
     * @param accessToken
     * @param vo
     * @return
     */
    public ResultBean<AggregateDataVo> aggregateData(String accessToken, AggregateDataVo vo) {
        log.info("AccountManageService aggregateData accessToken={},AggregateDataVo={}", accessToken, vo);
        try {
            AggregateDataVo data = new AggregateDataVo();
            BeanUtils.copyProperties(data, vo);
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            // 校验登录信息
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }

            Long orgId = tokenRedisVo.getEnterpriseId();

            if (vo.getMonthType() == null || vo.getYear() == null || vo.getMonthPayment() == null || vo.getYearPayment() == null) {
                return ResultBean.failedResultOfParamWithMsg("参数有误");
            }


            // 租金
            String rentSql = "SELECT  b.`id`,b.`house_id` AS houseId,b.`community_id` AS communityId,a1.name as name1,a2.name as name2,b.`building_num` AS buildingNum,\n" +
                    "b.`unit`,b.`room_number` AS roomNumber,b.`org_id` AS orgId,b.`match_user_id` AS matchUserId,if(b.`charge_type`=1,8,9) AS chargeType,\n" +
                    "b.`measure_unit` AS measureUnit,b.`cost`, b.`start_time`  AS startTime, b.`end_time` AS endTime, b.`audit_status` AS auditStatus,b.`payment_status`  AS paymentStatus,\n" +
                    "b.`payment_time` AS paymentTime,b.`payment_channel` AS paymentChannel,null AS operatorId,null AS lastUpdateTime,b.`create_time` AS createTime,\n" +
                    "b.should_pay_time AS shouldPayTime,2 as houseType  ,\n" +
                    "(select i.create_time  from  saas_backlog_item_bill ib   \n" +
                    "LEFT JOIN  `saas_backlog_item` i  ON i.`id` = ib.backlog_item_id   \n" +
                    "where ib.`bill_id` = b.id  GROUP BY i.create_time DESC LIMIT 1) AS  itemTime ,\n" +
                    "IFNULL(u.name,ui.name) as name,\n" +
                    "IFNULL(u.mobile,ui.phone) as phone,b.surplus_cost as surplusCost,\n" +
                    "br.collection_org as collectionOrg \n" +
                    "FROM `saas_estate_rent_bill` b \n" +
                    "LEFT JOIN  `saas_app_user` a1  ON a1.`id` = b.match_user_id \n" +
                    "LEFT JOIN  `saas_app_user` a2  ON a2.`enterprise_user_id` = b.match_user_id\n" +
                    "LEFT JOIN  `saas_community_house_user` u  ON u.`community_house_id` = b.house_id and u.status=1 and u.type=1\n" +
                    "LEFT JOIN  (select a.house_id ,b.name ,c.phone from  saas_house_match_user a \n" +
                    "LEFT JOIN saas_house_eligible_apply b on b.id = a.apply_id\n" +
                    "LEFT JOIN saas_app_user c on c.id = a.match_user_id \n" +
                    "where  a.status=1 ) ui  ON ui.`house_id` = b.house_id " +
                    "LEFT JOIN saas_house_expense_bill_rule br ON b.rule_id = br.id";

            // 账单
            String billSql = "SELECT  b.`id`,b.`house_id` AS houseId,b.`community_id` AS communityId,a1.name as name1,a2.name as name2,b.`building_num` AS buildingNum,b.`unit`,\n" +
                    "b.`room_number` AS roomNumber,b.`org_id` AS orgId,b.`match_user_id` AS matchUserId,b.`charge_type` AS chargeType,\n" +
                    "b.`measure_unit` AS measureUnit,b.`cost`, b.`start_time`  AS startTime, b.`end_time` AS endTime, b.`audit_status` AS auditStatus,\n" +
                    "b.`payment_status`  AS paymentStatus,b.`payment_time` AS paymentTime,b.`payment_channel` AS paymentChannel,\n" +
                    "b.`operator_id` AS operatorId,b.`last_update_time` AS lastUpdateTime,b.`create_time` AS createTime,b.should_pay_time AS shouldPayTime,2 as houseType ,(select i.create_time  from  saas_backlog_item_bill ib   \n" +
                    "LEFT JOIN  `saas_backlog_item` i  ON i.`id` = ib.backlog_item_id   \n" +
                    "where ib.`bill_id` = b.id  GROUP BY i.create_time DESC LIMIT 1 ) AS  itemTime  ,\n" +
                    "IFNULL(u.name,ui.name) as name,\n" +
                    "IFNULL(u.mobile,ui.phone) as phone, b.surplus_cost as surplusCost,\n" +
                    "br.collection_org as collectionOrg \n " +
                    "FROM `saas_estate_expense_bill` b \n" +
                    "LEFT JOIN  `saas_app_user` a1  ON a1.`id` = b.match_user_id \n" +
                    "LEFT JOIN  `saas_app_user` a2  ON a2.`enterprise_user_id` = b.match_user_id\n" +
                    "LEFT JOIN  `saas_community_house_user` u  ON u.`community_house_id` = b.house_id and u.status=1 and u.type=1\n" +
                    "LEFT JOIN  (select a.house_id ,b.name ,c.phone from  saas_house_match_user a \n" +
                    "LEFT JOIN saas_house_eligible_apply b on b.id = a.apply_id\n" +
                    "LEFT JOIN saas_app_user c on c.id = a.match_user_id \n" +
                    "where  a.status=1 ) ui  ON ui.`house_id` = b.house_id " +
                    "LEFT JOIN saas_house_expense_bill_rule br ON b.rule_id = br.id";

            // 账单户数
            String billCountSql = "SELECT  b.`id`,b.`house_id` AS houseId,b.`community_id` AS communityId,b.`building_num` AS buildingNum, \n" +
                    "b.`unit`,b.`room_number` AS roomNumber,b.`org_id` AS orgId,b.`match_user_id` AS matchUserId,if(b.`charge_type`=1,8,9) AS chargeType, \n" +
                    "b.`measure_unit` AS measureUnit,b.`cost`, b.`start_time`  AS startTime, b.`end_time` AS endTime, b.`audit_status` AS auditStatus,if(b.`payment_status` = 2,0,b.`payment_status`)  AS paymentStatus, \n" +
                    "b.`payment_time` AS paymentTime,b.`payment_channel` AS paymentChannel,null AS operatorId,null AS lastUpdateTime,b.`create_time` AS createTime, \n" +
                    "b.should_pay_time AS shouldPayTime,2 as houseType  \n" +
                    "FROM `saas_estate_rent_bill` b  \n" +
                    " GROUP BY b.house_id  \n" +
                    "UNION ALL \n" +
                    "SELECT  b.`id`,b.`house_id` AS houseId,b.`community_id` AS communityId,b.`building_num` AS buildingNum,b.`unit`, \n" +
                    "b.`room_number` AS roomNumber,b.`org_id` AS orgId,b.`match_user_id` AS matchUserId,b.`charge_type` AS chargeType, \n" +
                    "b.`measure_unit` AS measureUnit,b.`cost`, b.`start_time`  AS startTime, b.`end_time` AS endTime, b.`audit_status` AS auditStatus,if(b.`payment_status` = 2,0,b.`payment_status`)  AS paymentStatus,b.`payment_time` AS paymentTime,b.`payment_channel` AS paymentChannel,b.`operator_id` AS operatorId,b.`last_update_time` AS lastUpdateTime,b.`create_time` AS createTime,b.should_pay_time AS shouldPayTime,2 as houseType \n" +
                    "FROM `saas_estate_expense_bill` b  \n" +
                    "GROUP BY  b.house_id";

            String totalBillSql = " select sum(v.cost ) as amount,sum(v.surplusCost) as surplusAmount  ,v.`paymentStatus` as paymentStatus from ( " + rentSql + " UNION ALL " + billSql + " ) v";
            String conditionBillSql = " select sum(v.cost ) as amount,sum(v.surplusCost) as surplusAmount  ,v.`paymentStatus` as paymentStatus from ( " + rentSql + " UNION ALL " + billSql + " ) v";
            String arrearsBillSql = " select sum(v.surplusCost) as amount ,CONCAT(YEAR(v.shouldPayTime),'-',MONTH(v.shouldPayTime)) as shouldPayTime from ( " + rentSql + " UNION ALL " + billSql + " ) v";
            String billDataSql = " select v.houseId as houseId ,v.`paymentStatus` as paymentStatus from (" + billCountSql + ") v";

            Date yesterday = DateUtil.offsetDay(new Date(), -1);
            // 当前时间前一天的23：59：59
            Date endTime = DateUtil.endOfDay(yesterday);
            List<Object> args = new ArrayList<>();
            List<Object> args1 = new ArrayList<>();
            List<Object> args2 = new ArrayList<>();
            List<Object> args5 = new ArrayList<>();
            StringBuilder where = new StringBuilder(" WHERE 1 = 1 ");
            StringBuilder where1 = new StringBuilder(" WHERE 1 = 1 ");
            StringBuilder where2 = new StringBuilder(" WHERE 1 = 1 ");
            StringBuilder where5 = new StringBuilder(" WHERE 1 = 1 ");
            List<String> communityIds = new ArrayList<>();
            // 权限过滤
            List<Map<String, Object>> communityList = appCommunityService.findCommunity(accessToken).getResultData();
            if (communityList != null && !communityList.isEmpty()) {
                where.append(" and v.communityId in " + SqlUtils.foreachIn(communityList.size()));
                where1.append(" and v.communityId in " + SqlUtils.foreachIn(communityList.size()));
                where2.append(" and v.communityId in " + SqlUtils.foreachIn(communityList.size()));
                where5.append(" and v.communityId in " + SqlUtils.foreachIn(communityList.size()));
                communityIds = communityList.stream().map(map -> {
                    String communityId = map.get("communityId").toString();
                    return communityId;
                }).collect(Collectors.toList());
                args.addAll(communityIds);
                args1.addAll(communityIds);
                args2.addAll(communityIds);
                args5.addAll(communityIds);
            } else {
                return ResultBean.successfulResult(null);
            }
            // 判断用户所属机构是否设置层级架构
            DepartmentHierarchy hierarchy = departmentHierarchyRepository.findByOrgIdAndStatus(orgId, 1);
            if (hierarchy == null) {
                return ResultBean.failedResultWithMsg("用户所属机构未设置层级架构");
            }
            // 查询出企业的标签
            Long id = hierarchy.getId();
            List<DepartmentEnterpriseTagRef> refs = departmentEnterpriseTagRefRepository.findByDepRefId(id);
            List<Long> enterpriseTagIds = refs.stream().map(DepartmentEnterpriseTagRef::getTagId).distinct().collect(Collectors.toList());// 用户企业标签

            if (!enterpriseTagIds.contains(3L)) {
                where.append("and v.collectionOrg = ? ");
                args.add(orgId);
                where1.append("and v.collectionOrg = ? ");
                args1.add(orgId);
            }

            if (!StringUtils.isEmpty(vo.getCommunityIds())) {
                where.append("and v.communityId = ? ");
                where1.append("and v.communityId = ? ");
                where2.append("and v.communityId = ? ");
                where5.append("and v.communityId = ? ");
                args.add(vo.getCommunityIds());
                args1.add(vo.getCommunityIds());
                args2.add(vo.getCommunityIds());
                args5.add(vo.getCommunityIds());
            }
            Date startTime = new Date();
            // 统计类型 0：月份账单 1：季度账单 2：年账单
            switch (vo.getMonthType()) {
                case 0:
                    startTime = DateUtil.beginOfMonth(endTime);
                    break;

                // 获取当前月份的季度最小时间
                case 1:
                    int month = DateUtil.month(endTime) + 1;
                    switch (month) {
                        case 1:
                        case 2:
                        case 3:
                            month = 1;
                            break;
                        case 4:
                        case 5:
                        case 6:
                            month = 4;
                            break;
                        case 7:
                        case 8:
                        case 9:
                            month = 7;
                            break;
                        case 10:
                        case 11:
                        case 12:
                            month = 10;
                            break;
                    }
                    // 构造季度最小时间的字符串
                    String quarterStartStr = StrUtil.format("{}-{}-01 00:00:00", DateUtil.year(endTime), month);
                    // 将季度最小时间字符串转换为DateTime类型
                    startTime = DateUtil.parse(quarterStartStr);
                    break;
                case 2:
                    startTime = DateUtil.beginOfYear(endTime);
                    break;
            }
            where1.append(" and v.startTime BETWEEN ? and ? ");
            args1.add(startTime);
            args1.add(endTime);

            where2.append(" and v.startTime BETWEEN ? and ? ");
            args2.add(DateUtils.format(vo.getYear().toString(), "yyyy", DateUtils.FORMAT_DATETIME_14));
            args2.add(endTime);

            // where5.append(" and v.startTime >= ? and v.startTime <= ? ");
            // args5.add(DateUtils.convert(DateUtils.getFirstDayOfMonth1(endTime), DateUtils.FORMAT_DATETIME_14));
            // args5.add(endTime);

            where2.append(" and v.shouldPayTime < ?  ");
            args2.add(endTime);

            where.append(" and v.auditStatus = 1  ");
            where1.append(" and v.auditStatus = 1  ");
            where2.append(" and v.auditStatus = 1  ");
            where5.append(" and v.auditStatus = 1  ");

            where5.append(" and v.orgId = ?  ");
            args5.add(orgId);

            where.append("  GROUP BY  v.paymentStatus ");
            where1.append("  GROUP BY  v.paymentStatus ");
            where5.append("  GROUP BY  v.houseId,v.paymentStatus  ");
            where2.append("  GROUP BY  v.shouldPayTime ");

            // log.info("SQL："+totalBillSql + where);
            // 总账单数据
            List<Map<String, Object>> totalMap = jdbcTemplate.queryForList(totalBillSql + where, args.toArray());
            // 条件数据
            List<Map<String, Object>> conditionMap = jdbcTemplate.queryForList(conditionBillSql + where1, args1.toArray());
            // 欠费统计
            List<Map<String, Object>> arrearsMap = jdbcTemplate.queryForList(arrearsBillSql + where2, args2.toArray());
            // 小区缴费数据
            List<Map<String, Object>> billDataMap = jdbcTemplate.queryForList(billDataSql + where5, args5.toArray());

            AccountVo totalAccount = new AccountVo();
            totalAccount.setReceivables("0");
            totalAccount.setReceived("0");
            totalAccount.setDueIn("0");
            totalAccount.setRefund("0");

            AccountVo timeConditionAccount = new AccountVo();
            timeConditionAccount.setReceivables("0");
            timeConditionAccount.setReceived("0");
            timeConditionAccount.setDueIn("0");
            timeConditionAccount.setRefund("0");

            Long totalReceivables = 0L;
            Long timeConditionReceivables = 0L;
            // 封装数据
            for (Map<String, Object> map : totalMap) {
                Long amount = Long.valueOf(String.valueOf(map.get("amount")));
                Long paymentStatus = Long.valueOf(String.valueOf(map.get("paymentStatus")));
                Long amount1 = amount + Long.valueOf(ConvertUtils.yuanToFen(totalAccount.getReceived()));
                if (paymentStatus == 0) {
                    totalAccount.setDueIn(ConvertUtils.fenConvertYuan(amount));
                } else if (paymentStatus == 1) {
                    totalAccount.setReceived(ConvertUtils.fenConvertYuan(amount1));
                } else if (paymentStatus == 2) {
                    Long surplusAmount = Long.valueOf(String.valueOf(map.get("surplusAmount")));
                    amount = amount - surplusAmount;
                    amount1 = amount + Long.valueOf(ConvertUtils.yuanToFen(totalAccount.getReceived()));
                    totalAccount.setReceived(ConvertUtils.fenConvertYuan(amount1));
                }
                totalReceivables += amount;
            }
            for (Map<String, Object> map : conditionMap) {
                Long amount = Long.valueOf(String.valueOf(map.get("amount")));
                Long paymentStatus = Long.valueOf(String.valueOf(map.get("paymentStatus")));
                Long amount1 = amount + Long.valueOf(ConvertUtils.yuanToFen(timeConditionAccount.getReceived()));
                if (paymentStatus == 0) {
                    timeConditionAccount.setDueIn(ConvertUtils.fenConvertYuan(amount));
                } else if (paymentStatus == 1) {
                    timeConditionAccount.setReceived(ConvertUtils.fenConvertYuan(amount1));
                } else if (paymentStatus == 2) {
                    Long surplusAmount = Long.valueOf(String.valueOf(map.get("surplusAmount")));
                    amount = amount - surplusAmount;
                    amount1 = amount + Long.valueOf(ConvertUtils.yuanToFen(timeConditionAccount.getReceived()));
                    timeConditionAccount.setReceived(ConvertUtils.fenConvertYuan(amount1));
                }
                timeConditionReceivables += amount1;
            }

            Map<String, String> map1 = new HashMap<>();
            for (Map<String, Object> map : arrearsMap) {
                Integer amount = Integer.valueOf(String.valueOf(map.get("amount")));
                String shouldPayTime = String.valueOf(map.get("shouldPayTime"));
                String s = map1.get(shouldPayTime);
                if (StrUtil.isNotEmpty(s)) {
                    Double aDouble = Convert.toDouble(s);
                    Double s1 = Convert.toDouble(ConvertUtils.fenConvertYuan(amount));
                    s = Convert.toStr(NumberUtil.add(aDouble, s1));
                    map1.put(shouldPayTime, s);
                } else {
                    Double s1 = Convert.toDouble(ConvertUtils.fenConvertYuan(amount));
                    map1.put(shouldPayTime, s1.toString());
                }
            }

            // 应缴
            Integer totalPayment = 0;
            // 未缴户数
            Integer unpaidPayment = 0;
            // 已缴户数
            Integer alreadyPayment = 0;

            data.setAlreadyPayment(alreadyPayment);
            data.setUnpaidPayment(unpaidPayment);
            Map<String, Integer> cont = new HashMap<>();
            for (Map<String, Object> map : billDataMap) {
                Integer paymentStatus = Integer.valueOf(String.valueOf(map.get("paymentStatus")));
                String houseId = String.valueOf(map.get("houseId"));
                Integer integer = cont.get(houseId);
                // 获取当前房屋是否有未缴,如有将当前覆盖
                if (integer != null) {
                    if (integer == 1) {
                        cont.put(houseId, paymentStatus);
                    }
                } else {
                    cont.put(houseId, paymentStatus);
                }
            }

            for (String s : cont.keySet()) {
                Integer integer = cont.get(s);
                if (integer == 0) {
                    unpaidPayment++;
                } else {
                    alreadyPayment++;
                }
                totalPayment++;
            }
            // 应缴户数
            data.setTotalPayment(totalPayment);
            data.setAlreadyPayment(alreadyPayment);
            data.setUnpaidPayment(unpaidPayment);

            totalAccount.setReceivables(ConvertUtils.fenConvertYuan(totalReceivables));
            timeConditionAccount.setReceivables(ConvertUtils.fenConvertYuan(timeConditionReceivables));

            List<HouseRemainingRecord> recordList = new ArrayList<>();
            Long refundTotal = 0L;

            // 余额退款记录
            for (String communityId : communityIds) {
                List<House> houseList = houseRepository.findByResidenceCommunityId(communityId);
                if (!CollectionUtils.isEmpty(houseList)) {
                    for (House house : houseList) {
                        HouseRemaining remaining = houseRemainingRepository.findByOrgIdAndHouseIdAndStatus(orgId, house.getId(), 6);
                        if (remaining != null) {
                            HouseRemainingRecord record = houseRemainingRecordRepository.findByRemainingIdAndOperateStatus(remaining.getId(), 3);
                            if (record != null) {
                                recordList.add(record);
                                refundTotal += record.getOperateMoney();
                            }
                        }
                    }
                }
            }
            Long refundCondition = 0L;
            // 获取时间内的退款金额
            for (HouseRemainingRecord record : recordList) {
                if (record.getLastUpdateTime().getTime() < endTime.getTime()
                        && record.getLastUpdateTime().getTime() > startTime.getTime()) {
                    refundCondition += record.getOperateMoney();
                }
            }

            totalAccount.setRefund(ConvertUtils.fenConvertYuan(refundTotal));
            timeConditionAccount.setRefund(ConvertUtils.fenConvertYuan(refundCondition));

            data.setTotalAccount(totalAccount);
            data.setTimeConditionAccount(timeConditionAccount);
            data.setArrearsAccount(map1);

            /*
            缴费统计 月份/年份
             */
            String accountSql = "SELECT IFNULL(SUM(rr.operate_money),0) as amount  , rr.bill_status as status  " +
                    "FROM saas_house_remaining  r " +
                    "LEFT JOIN saas_house  h on r.house_id = h.id " +
                    "LEFT JOIN saas_house_remaining_record rr ON r.id = rr.remaining_id " +
                    "WHERE 1 = 1 and rr.bill_status IN (4,5) and rr.`status` = 1  ";


            AccountVo monthAccount = new AccountVo();
            AccountVo yearAccount = new AccountVo();

            List<Object> args3 = new ArrayList<>();
            List<Object> args4 = new ArrayList<>();
            StringBuilder where3 = new StringBuilder();
            StringBuilder where4 = new StringBuilder();

            where3.append(" and h.residence_community_id IN " + SqlUtils.foreachIn(communityIds.size()));
            args3.addAll(communityIds);
            where4.append(" and h.residence_community_id IN " + SqlUtils.foreachIn(communityIds.size()));
            args4.addAll(communityIds);


            if (!StringUtils.isEmpty(vo.getCommunityIds())) {
                where3.append("and h.residence_community_id = ? ");
                where4.append("and h.residence_community_id = ? ");
                args3.add(vo.getCommunityIds());
                args4.add(vo.getCommunityIds());
            }

            if (!StringUtils.isEmpty(vo.getMonthPayment())) {
                where3.append(" and date_format(rr.last_update_time,'%Y-%m') =  ?  ");
                args3.add(vo.getMonthPayment());
            }

            if (!StringUtils.isEmpty(vo.getYearPayment())) {
                where4.append(" and date_format(rr.last_update_time,'%Y') =  ?  ");
                args4.add(vo.getYearPayment());
            }

            where3.append(" GROUP BY rr.bill_status ");
            where4.append(" GROUP BY rr.bill_status ");
            List<Map<String, Object>> monthAmount = new ArrayList<>();
            List<Map<String, Object>> yearAmount = new ArrayList<>();
            monthAmount = jdbcTemplate.queryForList(accountSql + where3, args3.toArray());
            yearAmount = jdbcTemplate.queryForList(accountSql + where4, args4.toArray());

            Integer monthTotal = 0;
            Integer yearTotal = 0;
            // 4线上充值 5线下充值
            for (Map<String, Object> map : monthAmount) {
                Integer status = Integer.valueOf(map.get("status").toString());
                Integer amount = Integer.valueOf(map.get("amount").toString());
                if (status == 4) {
                    monthAccount.setOnline(ConvertUtils.fenConvertYuan(amount));
                    monthTotal += amount;
                } else if (status == 5) {
                    monthAccount.setOffline(ConvertUtils.fenConvertYuan(amount));
                    monthTotal += amount;
                }

            }

            for (Map<String, Object> map : yearAmount) {
                Integer status = Integer.valueOf(map.get("status").toString());
                Integer amount = Integer.valueOf(map.get("amount").toString());
                if (status == 4) {
                    yearAccount.setOnline(ConvertUtils.fenConvertYuan(amount));
                    yearTotal += amount;
                } else if (status == 5) {
                    yearAccount.setOffline(ConvertUtils.fenConvertYuan(amount));
                    yearTotal += amount;
                }


            }


            monthAccount.setTotal(ConvertUtils.fenConvertYuan(monthTotal));
            yearAccount.setTotal(ConvertUtils.fenConvertYuan(yearTotal));
            if (StringUtils.isEmpty(monthAccount.getOnline())) {
                monthAccount.setOnline("0");
            }
            if (StringUtils.isEmpty(monthAccount.getOffline())) {
                monthAccount.setOffline("0");
            }
            if (StringUtils.isEmpty(yearAccount.getOnline())) {
                yearAccount.setOnline("0");
            }
            if (StringUtils.isEmpty(yearAccount.getOffline())) {
                yearAccount.setOffline("0");
            }

            data.setMonthAccount(monthAccount);
            data.setYearAccount(yearAccount);
            return ResultBean.successfulResult(data);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }


    /**
     * 账单列表-列表信息显示
     *
     * @param accessToken
     * @param pageNumber
     * @param pageSize
     * @param type
     * @param filter      查询对应权限账单 并更新催缴记录
     */
    public ResultBean<Object> otherBills(String accessToken, Integer pageNumber, Integer pageSize, Integer type, BillSearchRequestVO filter) {
        log.info("EstateBillService billListShow accessToken={},pageNumber={},pageSize={},type={}", accessToken, pageNumber, pageSize, type);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        ApiData<Map<String, Object>> apiData = new ApiData<>();
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            // 校验登录信息
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }

            String userId = tokenRedisVo.getId();

            // 租金
            String rentSql = "SELECT  b.`id`,b.`house_id` AS houseId,b.`community_id` AS communityId,a1.name as name1,a2.name as name2,b.`building_num` AS buildingNum,\n" +
                    "b.`unit`,b.`room_number` AS roomNumber,b.`org_id` AS orgId,b.`match_user_id` AS matchUserId,if(b.`charge_type`=1,8,9) AS chargeType,\n" +
                    "b.`measure_unit` AS measureUnit,b.`cost`, b.`start_time`  AS startTime, b.`end_time` AS endTime, b.`audit_status` AS auditStatus,b.`payment_status`  AS paymentStatus,\n" +
                    "b.`payment_time` AS paymentTime,b.`payment_channel` AS paymentChannel,null AS operatorId,null AS lastUpdateTime,b.`create_time` AS createTime,\n" +
                    "b.should_pay_time AS shouldPayTime,2 as houseType  ,\n" +
                    "IFNULL(u.name,ui.name) as name,\n" +
                    "IFNULL(u.mobile,ui.phone) as phone,br.violate_status as violateStatus , br.violate_ratio as violateRatio , \n" +
                    "br.collection_org as collectionOrg , b.adjust_status as adjustStatus , eab.adjust_cost as adjustCost ,  eab.cost as adjustAfterCost , eab.status as adjustAfterStatus , eab.adjust_type as adjustType , eab.operator_id as adjustOperatorId ,eab.completion_time as adjustCompletionTime," +
                    "eab.status as adjustPaymentStatus\n" +
                    "FROM   saas_estate_adjust_bill eab \n" +
                    "LEFT JOIN `saas_estate_rent_bill` b ON b.id = eab.bill_id " +
                    "LEFT JOIN  `saas_app_user` a1  ON a1.`id` = b.match_user_id \n" +
                    "LEFT JOIN  `saas_app_user` a2  ON a2.`enterprise_user_id` = b.match_user_id\n" +
                    "LEFT JOIN  `saas_community_house_user` u  ON u.`community_house_id` = b.house_id and u.status=1 and u.type=1\n" +
                    "LEFT JOIN  (select a.house_id ,b.name ,c.phone from  saas_house_match_user a \n" +
                    "LEFT JOIN saas_house_eligible_apply b on b.id = a.apply_id\n" +
                    "LEFT JOIN saas_app_user c on c.id = a.match_user_id \n" +
                    "where  a.status=1 ) ui  ON ui.`house_id` = b.house_id " +
                    "LEFT JOIN saas_house_expense_bill_rule br ON b.rule_id = br.id " +
                    "where eab.bill_type = 1    ";


            // 账单
            String billSql = "SELECT  b.`id`,b.`house_id` AS houseId,b.`community_id` AS communityId,a1.name as name1,a2.name as name2,b.`building_num` AS buildingNum,b.`unit`,\n" +
                    "b.`room_number` AS roomNumber,b.`org_id` AS orgId,b.`match_user_id` AS matchUserId,b.`charge_type` AS chargeType,\n" +
                    "b.`measure_unit` AS measureUnit,b.`cost`, b.`start_time`  AS startTime, b.`end_time` AS endTime, b.`audit_status` AS auditStatus,\n" +
                    "b.`payment_status`  AS paymentStatus,b.`payment_time` AS paymentTime,b.`payment_channel` AS paymentChannel,\n" +
                    "b.`operator_id` AS operatorId,b.`last_update_time` AS lastUpdateTime,b.`create_time` AS createTime,b.should_pay_time AS shouldPayTime,2 as houseType ,\n" +
                    "IFNULL(u.name,ui.name) as name,\n" +
                    "IFNULL(u.mobile,ui.phone) as phone,br.violate_status as violateStatus , br.violate_ratio as violateRatio , \n" +
                    "br.collection_org as collectionOrg , b.adjust_status as adjustStatus , eab.adjust_cost as adjustCost , eab.cost as adjustAfterCost , eab.status as adjustAfterStatus , eab.adjust_type as adjustType , eab.operator_id as adjustOperatorId ,eab.completion_time as adjustCompletionTime," +
                    "eab.status as adjustPaymentStatus\n " +
                    "FROM saas_estate_adjust_bill eab\n" +
                    "LEFT JOIN `saas_estate_expense_bill` b  ON b.id = eab.bill_id \n" +
                    "LEFT JOIN  `saas_app_user` a1  ON a1.`id` = b.match_user_id \n" +
                    "LEFT JOIN  `saas_app_user` a2  ON a2.`enterprise_user_id` = b.match_user_id\n" +
                    "LEFT JOIN  `saas_community_house_user` u  ON u.`community_house_id` = b.house_id and u.status=1 and u.type=1\n" +
                    "LEFT JOIN  (select a.house_id ,b.name ,c.phone from  saas_house_match_user a \n" +
                    "LEFT JOIN saas_house_eligible_apply b on b.id = a.apply_id\n" +
                    "LEFT JOIN saas_app_user c on c.id = a.match_user_id \n" +
                    "where  a.status=1 ) ui  ON ui.`house_id` = b.house_id " +
                    "LEFT JOIN saas_house_expense_bill_rule br ON b.rule_id = br.id " +
                    "where eab.bill_type = 2    ";
            /*String rentSql2 = "SELECT  b.`id`,b.`house_id` AS houseId,b.`community_id` AS communityId,a1.name as name1,a2.name as name2,b.`building_num` AS buildingNum,b.`unit`,"
                    + "b.`room_number` AS roomNumber,h.house_property_id AS orgId,b.`match_user_id` AS matchUserId,if(b.`charge_type`=1,8,9) AS chargeType,"
                    + "b.`measure_unit` AS measureUnit,b.`cost`, b.`start_time`  AS startTime, b.`end_time` AS endTime, b.`audit_status` AS auditStatus,"
                    + "b.`payment_status`  AS paymentStatus,b.`payment_time` AS paymentTime,b.`payment_channel` AS paymentChannel,"
                    + "null AS operatorId,null AS lastUpdateTime,b.`create_time` AS createTime,b.should_pay_time AS shouldPayTime,1 as houseType  "
                    + "FROM `saas_rent_bill` b "
                    + "LEFT JOIN  `saas_house` h  ON h.id = b.house_id "
                    + "LEFT JOIN  `saas_app_user` a1  ON a1.`id` = b.match_user_id "
                    + "LEFT JOIN  `saas_app_user` a2  ON a2.`enterprise_user_id` = b.match_user_id ";

            String billSq2 = "SELECT  b.`id`,b.`house_id` AS houseId,b.`community_id` AS communityId,a1.name as name1,a2.name as name2,b.`building_num` AS buildingNum,b.`unit`,"
                    + "b.`room_number` AS roomNumber,h.house_property_id AS orgId,b.`match_user_id` AS matchUserId,b.`charge_type` AS chargeType,"
                    + "b.`measure_unit` AS measureUnit,b.`cost`, b.`start_time`  AS startTime, b.`end_time` AS endTime, b.`audit_status` AS auditStatus,"
                    + "b.`payment_status`  AS paymentStatus,b.`payment_time` AS paymentTime,b.`payment_channel` AS paymentChannel,"
                    + "b.`operator_id` AS operatorId,b.`last_update_time` AS lastUpdateTime,b.`create_time` AS createTime,b.should_pay_time AS shouldPayTime,1 as houseType  "
                    + "FROM `saas_expense_bill` b "
                    + "LEFT JOIN  `saas_house` h  ON h.id = b.house_id "
                    + "LEFT JOIN  `saas_app_user` a1  ON a1.`id` = b.match_user_id "
                    + "LEFT JOIN  `saas_app_user` a2  ON a2.`enterprise_user_id` = b.match_user_id ";*/

            billSql = " select v.* from ( " + rentSql + " UNION ALL " + billSql + " ) v";

            List<Object> args = new ArrayList<>();
            StringBuilder where = new StringBuilder(" ");
            // 权限过滤
            List<Map<String, Object>> communityList = appCommunityService.findCommunity(accessToken).getResultData();
            if (communityList != null && !communityList.isEmpty()) {
                where.append(" and v.communityId in " + SqlUtils.foreachIn(communityList.size()));
                List<String> communityIds = communityList.stream().map(map -> {
                    String communityId = map.get("communityId").toString();
                    return communityId;
                }).collect(Collectors.toList());
                args.addAll(communityIds);
            } else {
                where.append(" and v.communityId in (null) ");
            }


            String offsets = "   LIMIT ? OFFSET ? ";

            // 条件查询
            if (org.apache.commons.lang3.StringUtils.isNotBlank(filter.getHouseId())) {
                where.append("  AND  v.`houseId` = ?  \n");
                args.add(filter.getHouseId());

                String matchUserId = null;
                List<MatchUserHouse> byHouseId = matchUserHouseRepository.findByHouseId(filter.getHouseId());
                if (!byHouseId.isEmpty()) {
                    String matchUserStockId = byHouseId.get(0).getMatchUserStockId();
                    //	根据承租人和房产的承租人id查询承认人表的房产承租人id
                    Optional<MatchUser> matchUserRepositoryById = matchUserRepository.findById(Long.parseLong(matchUserStockId));
                    if (matchUserRepositoryById.isPresent()) {
                        // 产权下的用户承租人id
                        MatchUser byMatchUserId = matchUserRepositoryById.get();
                        // 产权下的用户承租人id
                        matchUserId = byMatchUserId.getMatchUserId();
                    }
                }
                where.append("  AND  v.`matchUserId` = ?  \n");
                args.add(matchUserId);
            }
            if (org.apache.commons.lang3.StringUtils.isNotBlank(filter.getCommunityId())) {
                where.append("  AND  v.`communityId` = ?  \n");
                args.add(filter.getCommunityId());
            }
            if (filter.getBuildingNum() != null) {
                where.append("  AND  v.`buildingNum` =  ?  \n");
                args.add(filter.getBuildingNum());
            }
            if (filter.getUnit() != null) {
                where.append("  AND  v.`unit` =  ?  \n");
                args.add(filter.getUnit());
            }
            if (org.apache.commons.lang3.StringUtils.isNotBlank(filter.getRoomNumber())) {
                where.append("  AND  v.`roomNumber` = ?  \n");
                args.add(filter.getRoomNumber());
            }
            if (filter.getOrgId() != null) {
                where.append("  AND  v.`orgId` =  ?  \n");
                args.add(filter.getOrgId());
            }
//            if (StringUtils.isNotBlank(filter.getMatchUserName())) {
//                where.append("  AND  (v.`name1` like ? or v.`name2` like ?)  \n");
//                args.add("%" + filter.getMatchUserName() + "%");
//                args.add("%" + filter.getMatchUserName() + "%");
//            }

            if (org.apache.commons.lang3.StringUtils.isNotBlank(filter.getMatchUserName())) {
                where.append("  AND  v.`name` like ?   \n");
                args.add("%" + filter.getMatchUserName() + "%");
            }

            if (filter.getChargeType() != null) {
                where.append("  AND  v.`chargeType` =  ?  \n");
                args.add(filter.getChargeType());
            }
            if (filter.getPaymentStatus() != null) {
                where.append("  AND  v.`paymentStatus` =  ?  \n");
                args.add(filter.getPaymentStatus());
            }

            if (filter.getPaymentChannel() != null) {
                where.append("  AND  v.`paymentChannel` =  ?  \n");
                args.add(filter.getPaymentChannel());
            }
            where.append("  AND  v.`adjustStatus` =  1  \n");

            List<Map<String, Object>> peopleList = new ArrayList<>();
            // 查询总记录数
            String count = "select count(1) FROM (" + billSql + " where 1 = 1  " + where + ") c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, args.toArray());
            // log.info("SQL :" + billSql + where);
            if (total == 0) {
                result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
                result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
                apiData.setData(peopleList);
                apiData.setTotal(total);
                result.setResultData(apiData);
                return result;
            }

            // 查询分页数据
            where.append("  ORDER BY ").append(" v.createTime desc ").append(" \n").append(offsets);
            args.add(pageSize);
            args.add(pageNumber * pageSize);

            peopleList = jdbcTemplate.queryForList(billSql + " where 1 = 1  " + where, args.toArray());

            String applySql = "select b.name ,c.phone from  saas_house_match_user a \n" +
                    "LEFT JOIN saas_house_eligible_apply b on b.id = a.apply_id\n" +
                    "LEFT JOIN saas_app_user c on c.id = a.match_user_id \n" +
                    "where a.house_id=? and a.status=1 ";
            // 封装账单数据
            for (Map<String, Object> map : peopleList) {
                Long id = Long.valueOf(String.valueOf(map.get("id")));
                String communityId = String.valueOf(map.get("communityId"));
                Long buildingNum = Long.valueOf(String.valueOf(map.get("buildingNum")));
                Long unit = Long.valueOf(String.valueOf(map.get("unit")));
                Long orgId = Long.valueOf(String.valueOf(map.get("orgId")));
                String matchUserId = String.valueOf(map.get("matchUserId"));
                String adjustOperatorId = String.valueOf(map.get("adjustOperatorId"));
                Integer chargeType = Integer.valueOf(String.valueOf(map.get("chargeType")));
                String cost = ConvertUtils.fenToYuan(String.valueOf(map.get("cost")));
                map.put("cost", cost);
                String adjustAfterCost = ConvertUtils.fenToYuan(String.valueOf(map.get("adjustAfterCost")));
                map.put("adjustAfterCost", adjustAfterCost);
                String adjustCost = ConvertUtils.fenToYuan(String.valueOf(map.get("adjustCost")));
                map.put("adjustCost", adjustCost);
                Object itemTime = map.get("itemTime");
                if (null == itemTime || org.apache.commons.lang3.StringUtils.isBlank(String.valueOf(itemTime))) {
                    map.put("display", 0);
                } else {
                    map.put("display", judgmentDate(String.valueOf(itemTime)));
                }

                map.put("paymentTime", String.valueOf(map.get("paymentTime")));


                String houseId = String.valueOf(map.get("houseId"));
                // List<MatchUserHouse> byHouseId = matchUserHouseRepository.findByHouseId(houseId);
                if (StringUtils.isNotBlank(matchUserId)) {
                    List<MatchUser> matchUserList = matchUserRepository.findByUserId(matchUserId);
                    if (CollectionUtil.isNotEmpty(matchUserList)) {
                        map.put("matchUserName", matchUserList.get(0).getName());
                        map.put("matchUserPhone", matchUserList.get(0).getPhone());
                        map.put("name", matchUserList.get(0).getName());
                    }
                }

                // if (!byHouseId.isEmpty()) {
                //     MatchUserHouse matchUserHouse = byHouseId.get(0);
                //     Integer label = matchUserHouse.getLabel();
                //     if (label == 1) {
                //         // 个人承租人
                //         List<CommunityHouseUser> communityHouseUserList = communityHouseUserRepository.findByCommunityHouseIdAndStatusAndType(houseId, 1, 1);
                //         if (communityHouseUserList != null && communityHouseUserList.size() > 0) {
                //             map.put("matchUserName", communityHouseUserList.get(0).getName());
                //             map.put("matchUserPhone", communityHouseUserList.get(0).getMobile());
                //             map.put("name", communityHouseUserList.get(0).getName());
                //         } else {
                //             if (org.apache.commons.lang3.StringUtils.isNotBlank(matchUserId)) {
                //                 Optional<AppUser> byId = appUserRepository.findById(matchUserId);
                //                 if (byId.isPresent()) {
                //                     map.put("matchUserName", byId.get().getName());
                //                     map.put("matchUserPhone", byId.get().getPhone());
                //                     map.put("name", byId.get().getName());
                //                 }
                //             }
                //         }
                //     } else {
                //         if (StringUtils.isNotEmpty(matchUserHouse.getMatchUserStockId())) {
                //             Optional<MatchUser> matchUserRepositoryById = matchUserRepository.findById(Long.parseLong(matchUserHouse.getMatchUserStockId()));
                //             if (matchUserRepositoryById.isPresent()) {
                //                 // 产权下的用户承租人id
                //                 MatchUser byMatchUserId = matchUserRepositoryById.get();
                //                 map.put("matchUserPhone", byMatchUserId.getPhone());
                //             }
                //             map.put("matchUserName", matchUserHouse.getCompanyName());
                //             map.put("name", matchUserHouse.getCompanyName());
                //         }
                //
                //     }
                // }


                Optional<Community> communityOptional = communityRepository.findById(communityId);
                // 获取小区名称
                if (communityOptional.isPresent()) {
                    Community community = communityOptional.get();
                    map.put("communityName", community.getName());
                }
                // 获取楼栋名称
                Optional<CommunityBuild> communityBuildOptional = communityBuildRepository.findById(buildingNum);
                if (communityBuildOptional.isPresent()) {
                    CommunityBuild communityBuild = communityBuildOptional.get();
                    map.put("buildingNumName", communityBuild.getName());
                }
                // 获取单元名称
                Optional<CommunityBuildUnit> communityBuildUnitOptional = communityBuildUnitRepository.findById(unit);
                if (communityBuildUnitOptional.isPresent()) {
                    CommunityBuildUnit communityBuildUnit = communityBuildUnitOptional.get();
                    map.put("unitName", communityBuildUnit.getName());
                }
                // 获取物业名称
                DepartmentHierarchy propertyUnit = departmentHierarchyRepository.findByOrgId(orgId);
                if (propertyUnit != null) {
                    map.put("orgName", propertyUnit.getName());
                }
                // 获取承租人名称、手机号
                // User lesseeUser = userRepository.findById(matchUserId);
//                AppUser lesseeUser = appUserRepository.findByIdOrEnterpriseUserId(matchUserId, matchUserId);
//                if (lesseeUser != null) {
//                    map.put("matchUserName", lesseeUser.getName());
//                    map.put("matchUserPhone", lesseeUser.getPhone());
//                    map.put("name", lesseeUser.getName());
//                }

                User adjustOperator = userRepository.findById(adjustOperatorId);
                if (adjustOperator != null) {
                    map.put("adjustOperatorName", adjustOperator.getName());
                }
                if (chargeType == 8) {
                    map.put("chargeTypeName", "租金");
                } else if (chargeType == 9) {
                    map.put("chargeTypeName", "押金");
                } else if (chargeType == 10) {
                    map.put("chargeTypeName", "退租");
                }
                Integer houseType = Integer.parseInt(String.valueOf(map.get("houseType")));
                if (houseType == 1) {
                    HouseWaitPaymentDetail expenseBillDetail = houseWaitPaymentDetailRepository.findByExpenseBillIdAndChargeType(id, chargeType);
                    if (expenseBillDetail != null) {
                        map.put("estateExpenseBillDetailId", expenseBillDetail.getId());
                        switch (chargeType) {
                            case 1:
                                map.put("chargeTypeName", "水费");
                                map.put("chargeTypeUnit", ConvertUtils.fenToYuan(String.valueOf(expenseBillDetail.getWaterUnitPrice())));
                                // map.put("chargeTypeUseNumber", estateExpenseBillDetail.getWaterUsage() + "吨");
                                map.put("startNum", expenseBillDetail.getWaterStartNum());
                                map.put("endNum", expenseBillDetail.getWaterEndNum());
                                map.put("usage", expenseBillDetail.getWaterUsage());
                                break;
                            case 2:
                                map.put("chargeTypeName", "电费");
                                map.put("chargeTypeUnit", ConvertUtils.fenToYuan(String.valueOf(expenseBillDetail.getElectricUnitPrice())));
                                // map.put("chargeTypeUseNumber", estateExpenseBillDetail.getElectricUsage() + "度");
                                map.put("startNum", expenseBillDetail.getElectricStartNum());
                                map.put("endNum", expenseBillDetail.getElectricEndNum());
                                map.put("usage", expenseBillDetail.getElectricUsage());
                                break;
                            case 3:
                                map.put("chargeTypeName", "物业费");
                                break;
                            case 4:
                                map.put("chargeTypeName", "宽带费");
                                break;
                            case 5:
                                map.put("chargeTypeName", "电视费");
                                break;
                            case 6:
                                map.put("chargeTypeName", "燃气费");
                                map.put("chargeTypeUnit", ConvertUtils.fenToYuan(String.valueOf(expenseBillDetail.getGasUnitPrice())));
                                map.put("startNum", expenseBillDetail.getGasStartNum());
                                map.put("endNum", expenseBillDetail.getGasEndNum());
                                map.put("usage", expenseBillDetail.getGasUsage());
                                break;
                            case 7:
                                map.put("chargeTypeName", "暖气费");
                                break;
                        }
                    }
                } else {
                    EstateExpenseBillDetail estateExpenseBillDetail = estateExpenseBillDetailRepository.findByExpenseBillIdAndChargeType(id, chargeType);
                    if (estateExpenseBillDetail != null) {
                        map.put("estateExpenseBillDetailId", estateExpenseBillDetail.getId());
                        switch (chargeType) {
                            case 1:
                                map.put("chargeTypeName", "水费");
                                map.put("chargeTypeUnit", ConvertUtils.fenToYuan(String.valueOf(estateExpenseBillDetail.getWaterUnitPrice())));
                                // map.put("chargeTypeUseNumber", estateExpenseBillDetail.getWaterUsage() + "吨");
                                map.put("startNum", estateExpenseBillDetail.getWaterStartNum());
                                map.put("endNum", estateExpenseBillDetail.getWaterEndNum());
                                map.put("usage", estateExpenseBillDetail.getWaterUsage());
                                break;
                            case 2:
                                map.put("chargeTypeName", "电费");
                                map.put("chargeTypeUnit", ConvertUtils.fenToYuan(String.valueOf(estateExpenseBillDetail.getElectricUnitPrice())));
                                // map.put("chargeTypeUseNumber", estateExpenseBillDetail.getElectricUsage() + "度");
                                map.put("startNum", estateExpenseBillDetail.getElectricStartNum());
                                map.put("endNum", estateExpenseBillDetail.getElectricEndNum());
                                map.put("usage", estateExpenseBillDetail.getElectricUsage());
                                break;
                            case 3:
                                map.put("chargeTypeName", "物业费");
                                break;
                            case 4:
                                map.put("chargeTypeName", "宽带费");
                                break;
                            case 5:
                                map.put("chargeTypeName", "电视费");
                                break;
                            case 6:
                                map.put("chargeTypeName", "燃气费");
                                map.put("chargeTypeUnit", ConvertUtils.fenToYuan(String.valueOf(estateExpenseBillDetail.getGasUnitPrice())));
                                map.put("startNum", estateExpenseBillDetail.getGasStartNum());
                                map.put("endNum", estateExpenseBillDetail.getGasEndNum());
                                map.put("usage", estateExpenseBillDetail.getGasUsage());
                                break;
                            case 7:
                                map.put("chargeTypeName", "暖气费");
                                break;
                        }
                    }
                }
            }

            apiData.setData(peopleList);
            apiData.setTotal(total);
            // LOG.info("SQL :" + billSql + where);
            result.setResultData(apiData);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /**
     * 调整账单支付
     *
     * @param accessToken token
     * @return
     */
    @Transactional
    public ResultBean<Object> otherBillsPay(String accessToken, Long billId, Integer chargeType) {
        String chargeName = null;
        switch (chargeType) {  //  1水费 2电费 3物业费 4宽带费 5电视费 6煤气费 7暖气费 8租金 9押金
            case 1:
                chargeName = "水费";
                break;
            case 2:
                chargeName = "电费";
                break;
            case 3:
                chargeName = "物业费";
                break;
            case 4:
                chargeName = "宽带费";
                break;
            case 5:
                chargeName = "电视费";
                break;
            case 6:
                chargeName = "燃气费";
                break;
            case 7:
                chargeName = "暖气费";
                break;
            case 8:
                chargeName = "租金";
                break;
            case 9:
                chargeName = "押金";
                break;
        }
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        String userId = tokenRedisVo.getId();
        // 校验登录信息
        if (tokenRedisVo == null) {
            result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
            result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
            return result;
        }


        if (billId == null) {
            result.setCode(StatusCode.ERROR_CODE_10004.getErrorCode());
            result.setMsg(StatusCode.ERROR_CODE_10004.getErrorMsg());
            return result;
        }

        // 校验账单是否存在
        if (chargeType.equals(8) || chargeType.equals(9)) {

            Optional<EstateRentBill> estateRentBillOptional = estateRentBillRepository.findById(billId);

            if (!estateRentBillOptional.isPresent()) {
                result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
                result.setMsg("账单不存在");
                return result;
            }
            EstateRentBill estateRentBill = estateRentBillOptional.get();
            Optional<EstateAdjustBill> estateAdjustBillOptional = estateAdjustBillRepository.findByBillIdAndBillType(billId, 1L);
            if (!estateAdjustBillOptional.isPresent()) {
                result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
                result.setMsg("账单不存在");
                return result;
            }
            EstateAdjustBill estateAdjustBill = estateAdjustBillOptional.get();
            Integer adjustType = estateAdjustBill.getAdjustType();
            if (adjustType.equals(1) || estateAdjustBill.getStatus().equals(1)) {
                result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
                result.setMsg("账单已支付");
                return result;
            }
            Integer adjustCost = estateAdjustBill.getAdjustCost();


            Long orgId = estateRentBill.getOrgId();
            String houseId = estateRentBill.getHouseId();


            HouseRemainingRelation rel = houseRemainingRelationRepository.findByOrgIdAndHouseId(orgId, houseId);
            if (rel == null) {
                result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
                result.setMsg("未找到账单对应余额账户  " + estateRentBill.getId());
                return result;
            }
            Optional<HouseRemaining> remaining = houseRemainingRepository.findById(rel.getRemainingId());
            if (!remaining.isPresent()) {
                result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
                result.setMsg("未找到账单对应余额账户  " + estateRentBill.getId());
                return result;
            }
            HouseRemaining houseRemaining = remaining.get();
            Integer balanceFee = houseRemaining.getBalanceFee();

            if (balanceFee < adjustCost) {
                result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
                result.setMsg("账户余额不足");
                return result;
            }
            balanceFee = balanceFee - adjustCost;
            houseRemaining.setBalanceFee(balanceFee);

            if (chargeType.equals(9)) {
                Integer cashPledge = houseRemaining.getCashPledge();
                houseRemaining.setCashPledge(cashPledge + adjustCost);
            }

            houseRemainingRepository.save(houseRemaining);


            // 余额操作记录
            DepartmentRemainingRecord record = new DepartmentRemainingRecord();
            record.setHouseId(estateRentBill.getHouseId());
            record.setBillId(estateRentBill.getId());
            record.setRemainingId(houseRemaining.getId());
            record.setOperateMoney(adjustCost);
            record.setOperatorId(userId);
            record.setUpdateTime(new Date());
            record.setUpdateStatus(1);
            record.setCause(PaymentCauseEnum.ADJUST_BILL.getValue() + estateRentBill.getStartTime().toString() + "-" + estateRentBill.getEndTime().toString() + "，" + chargeName);
            record.setOperateStatus(PaymentTypeEnum.BUCKLE.getValue());
            record.setBillStatus(chargeType);
            record.setStatus(1);
            departmentRemainingRecordRepository.save(record);

            estateAdjustBill.setStatus(1);
            estateAdjustBillRepository.save(estateAdjustBill);

        } else {
            Optional<EstateExpenseBill> estateExpenseBillOptional = estateExpenseBillRepository.findById(billId);

            if (!estateExpenseBillOptional.isPresent()) {
                result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
                result.setMsg("账单不存在");
                return result;
            }
            EstateExpenseBill estateExpenseBill = estateExpenseBillOptional.get();
            Optional<EstateAdjustBill> estateAdjustBillOptional = estateAdjustBillRepository.findByBillIdAndBillType(billId, 2L);
            if (!estateAdjustBillOptional.isPresent()) {
                result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
                result.setMsg("账单不存在");
                return result;
            }
            EstateAdjustBill estateAdjustBill = estateAdjustBillOptional.get();
            Integer adjustType = estateAdjustBill.getAdjustType();
            if (adjustType.equals(1) || estateAdjustBill.getStatus().equals(1)) {
                result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
                result.setMsg("账单已支付");
                return result;
            }
            Integer adjustCost = estateAdjustBill.getAdjustCost();


            Long orgId = estateExpenseBill.getOrgId();
            String houseId = estateExpenseBill.getHouseId();


            HouseRemainingRelation rel = houseRemainingRelationRepository.findByOrgIdAndHouseId(orgId, houseId);
            if (rel == null) {
                result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
                result.setMsg("未找到账单对应余额账户  " + estateExpenseBill.getId());
                return result;
            }
            Optional<HouseRemaining> remaining = houseRemainingRepository.findById(rel.getRemainingId());
            if (!remaining.isPresent()) {
                result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
                result.setMsg("未找到账单对应余额账户  " + estateExpenseBill.getId());
                return result;
            }
            HouseRemaining houseRemaining = remaining.get();
            Integer balanceFee = houseRemaining.getBalanceFee();

            if (balanceFee < adjustCost) {
                result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
                result.setMsg("账户余额不足");
                return result;
            }
            balanceFee = balanceFee - adjustCost;
            houseRemaining.setBalanceFee(balanceFee);
            houseRemainingRepository.save(houseRemaining);


            // 余额操作记录
            DepartmentRemainingRecord record = new DepartmentRemainingRecord();
            record.setHouseId(estateExpenseBill.getHouseId());
            record.setBillId(estateExpenseBill.getId());
            record.setRemainingId(houseRemaining.getId());
            record.setOperateMoney(adjustCost);
            record.setOperatorId(userId);
            record.setUpdateTime(new Date());
            record.setUpdateStatus(1);
            record.setCause(PaymentCauseEnum.ADJUST_BILL.getValue() + estateExpenseBill.getStartTime().toString() + "-" + estateExpenseBill.getEndTime().toString() + "，" + chargeName);
            record.setOperateStatus(PaymentTypeEnum.BUCKLE.getValue());
            record.setBillStatus(chargeType);
            record.setStatus(1);
            departmentRemainingRecordRepository.save(record);

            estateAdjustBill.setStatus(1);
            estateAdjustBillRepository.save(estateAdjustBill);
        }

        return result;


    }

    /**
     * 账户管理-缴费凭证管理 凭证列表
     *
     * @param accessToken
     * @param pageNumber
     * @param pageSize
     * @param residenceCommunityId 小区
     * @param buildingNum          楼栋
     * @param unit                 单元
     * @param roomNumber           房号
     * @param name                 承租人名
     * @param status               审核状态 0未审核 1已通过 2未通过
     * @param orgId                机构id
     * @return
     */
    public ResultBean<ApiData<PaymentVoucherVo>> paymentVoucherList(String accessToken, Integer pageNumber,
                                                                    Integer pageSize, String residenceCommunityId, Long buildingNum, Long unit, String roomNumber, String name, Integer status, Long orgId, Long accountType) {
        try {
            ApiData<PaymentVoucherVo> apiData = new ApiData<>();
            List<PaymentVoucherVo> data = new ArrayList();
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            // 校验登录信息
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }


            Long enterpriseId = tokenRedisVo.getEnterpriseId();

            if (status == null || orgId == null) {
                return ResultBean.failedResultOfParamWithMsg("参数有误");
            }

            String paymentSql = "SELECT\n" +
                    " opd.id,\n" +
                    " opd.remaining_id as remainingId,\n" +
                    " h.residence_community_id AS communityId,\n" +
                    " h.`building_num` AS buildingNum,\n" +
                    " h.`unit` AS unit,\n" +
                    " h.`room_number` AS roomNumber,\n" +
                    " opd.org_id as orgId,\n" +
                    " opd.match_user_id AS matchUserId,\n" +
                    " hu.NAME AS matchUserName,\n" +
                    " hu.mobile AS phone,\n" +
                    " opd.create_time as createTime,\n" +
                    " opd.operate_money AS operateMoney,\n" +
                    " opd.operator_id AS operatorId,\n" +
                    " opd.`status` AS updateStatus,\n" +
                    " h.id AS houseId,\n" +
                    " opd.last_update_time as lastUpdateTime,\n" +
                    " opd.payment_voucher as paymentVoucher,\n" +
                    " opd.voucher_number as voucherNumber,\n" +
                    " opd.create_user_id as createUserId, \n" +
                    " opd.account_type as accountType \n" +
                    " FROM\n" +
                    " saas_house_offline_payment_details opd \n" +
                    " LEFT JOIN saas_house h ON opd.house_id = h.id \n" +
                    " LEFT JOIN saas_community_house_user hu ON hu.`community_house_id` = opd.house_id \n" +
                    " AND hu.STATUS = 1 \n" +
                    " AND hu.type =1\n" +
                    " LEFT JOIN saas_user u ON opd.create_user_id = u.id \n" +
                    " AND u.`status` = 1" +
                    " LEFT JOIN saas_department_remaining dr ON dr.id = opd.remaining_id ";


            List<Object> args = new ArrayList<>();
            StringBuilder where = new StringBuilder(" WHERE 1 = 1 and opd.org_id = ?");
            args.add(orgId);

            String offsets = "   LIMIT ? OFFSET ? ";
            // 房屋账户
            if (accountType == null || accountType == 0) {
                // 权限过滤
                List<Map<String, Object>> communityList = appCommunityService.findCommunity(accessToken).getResultData();
                if (communityList != null && !communityList.isEmpty()) {
                    where.append(" and  h.residence_community_id in " + SqlUtils.foreachIn(communityList.size()));
                    List<String> communityIds = communityList.stream().map(map -> {
                        String communityId = map.get("communityId").toString();
                        return communityId;
                    }).collect(Collectors.toList());
                    args.addAll(communityIds);
                } else {
                    where.append(" and  h.residence_community_id in (null) ");
                }


                if (StringUtils.isNotBlank(residenceCommunityId)) {
                    where.append("  AND  h.residence_community_id = ?  \n");
                    args.add(residenceCommunityId);
                }
                if (buildingNum != null) {
                    where.append("  AND  h.`building_num` =  ?  \n");
                    args.add(buildingNum);
                }
                if (unit != null) {
                    where.append("  AND  h.`unit` =  ?  \n");
                    args.add(unit);
                }
                if (StringUtils.isNotBlank(roomNumber)) {
                    where.append("  AND  h.`room_number` = ?  \n");
                    args.add(roomNumber);
                }

                if (StringUtils.isNotBlank(name)) {
                    where.append("  AND  hu.`name` like ?   \n");
                    args.add("%" + name + "%");
                }
            } else {
                // 单位账户
                where.append("  AND  opd.`org_id`  = ?   \n");
                args.add(enterpriseId);


                if (StringUtils.isNotBlank(name)) {
                    where.append("  AND  dr.`dep_name` like ?   \n");
                    args.add("%" + name + "%");
                }
            }


            if (accountType != null) {
                where.append("  AND  opd.account_type = ?   \n");
                args.add(accountType);
            }

            // 审核状态 ：0未审核 1已通过 2未通过
            if (status != 0) {
                if (status == 1) {
                    where.append(" AND opd.status =  0  ");
                } else if (status == 2) {
                    where.append(" AND opd.status =  1  ");
                } else if (status == 3) {
                    where.append(" AND opd.status =  2  ");
                }
            }


            // 查询总记录数
            String count = "select count(1) FROM (" + paymentSql + where + ") c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, args.toArray());
            // log.info("SQL :" + billSql + where);
            if (total == 0) {
                apiData.setData(data);
                apiData.setTotal(total);
                return ResultBean.successfulResult(apiData);
            }


            where.append("  ORDER BY ").append(" opd.create_time desc,opd.id desc ").append(" \n").append(offsets);
            args.add(pageSize);
            args.add(pageNumber * pageSize);

            data = jdbcTemplate.query(paymentSql + where, new BeanPropertyRowMapper<>(PaymentVoucherVo.class), args.toArray());
            // 封装数据
            for (PaymentVoucherVo vo : data) {
                if (accountType == null || accountType == 0) {
                    Optional<Community> communityOptional = communityRepository.findById(vo.getCommunityId());
                    // 获取小区名称
                    if (communityOptional.isPresent()) {
                        Community community = communityOptional.get();
                        vo.setCommunityName(community.getName());
                    }
                    // 获取楼栋名称
                    Optional<CommunityBuild> communityBuildOptional = communityBuildRepository.findById(vo.getBuildingNum());
                    if (communityBuildOptional.isPresent()) {
                        CommunityBuild communityBuild = communityBuildOptional.get();
                        vo.setBuildingNumName(communityBuild.getName());
                    }
                    // 获取单元名称
                    Optional<CommunityBuildUnit> communityBuildUnitOptional = communityBuildUnitRepository.findById(vo.getUnit());
                    if (communityBuildUnitOptional.isPresent()) {
                        CommunityBuildUnit communityBuildUnit = communityBuildUnitOptional.get();
                        vo.setUnitName(communityBuildUnit.getName());
                    }
                }

                // 获取承租人名称、手机号
                if (vo.getAccountType() == 0) {
                    if (vo.getPhone() == null || vo.getMatchUserName() == null) {
                        AppUser lesseeUser = appUserRepository.findByIdOrEnterpriseUserId(vo.getMatchUserId(), vo.getMatchUserId());
                        if (lesseeUser != null) {
                            vo.setMatchUserName(lesseeUser.getName());
                            vo.setPhone(lesseeUser.getPhone());
                        }
                    }
                } else {
                    // 单位账户承租人
                    Optional<DepartmentRemaining> byId = departmentRemainingRepository.findById(vo.getRemainingId());
                    if (byId.isPresent()) {
                        DepartmentRemaining departmentRemaining = byId.get();
                        vo.setMatchUserName(departmentRemaining.getDepName());
                    }
                }


                // 获取操作人名称
                if (!StringUtils.isEmpty(vo.getOperatorId())) {
                    User operatorUser = userRepository.findById(vo.getOperatorId());
                    if (operatorUser != null) {
                        vo.setOperatorName(operatorUser.getName());
                    }
                }
                // 获取创建人名称
                if (!StringUtils.isEmpty(vo.getCreateUserId())) {
                    User createUser = userRepository.findById(vo.getCreateUserId());
                    if (createUser != null) {
                        vo.setCreateUserName(createUser.getName());
                    }
                }
                vo.setOperateMoney(ConvertUtils.fenConvertYuan(Long.parseLong(vo.getOperateMoney())));
            }

            apiData.setData(data);
            apiData.setTotal(total);
            return ResultBean.successfulResult(apiData);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }


    /**
     * 账户管理-缴费凭证管理 缴费凭证审核
     *
     * @param accessToken
     * @param status      审核类型 0通过 1不通过
     * @param voucherIds  凭证id
     * @return
     */
    public ResultBean<Object> voucherAudit(String accessToken, Integer status, List<Long> voucherIds) {
        log.info("AccountManageService  voucherAudit  status={},voucherIds={}", status, voucherIds);
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            // 校验登录信息
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }
            // 校验是否有权限进行审核
            Boolean flag = checkAuditor(accessToken, 1);
            if (!flag) {
                return ResultBean.failedResultWithMsg("审核权限未授权,请联系管理员授权");
            }

            String userId = tokenRedisVo.getId();
            String userName = tokenRedisVo.getName();


            if (status != 0 && status != 1) {
                return ResultBean.failedResultOfParamWithMsg("审核状态有误");
            }
            if (voucherIds.isEmpty()) {
                return ResultBean.failedResultOfParamWithMsg("参数有误");
            }

            // 凭证列表
            List<HouseOfflinePaymentDetails> paymentDetails = houseOfflinePaymentDetailsRepository.findByIdIn(voucherIds);
            Date date = new Date();
            if (paymentDetails.isEmpty()) {
                return ResultBean.failedResultOfParamWithMsg("未查询到凭证信息！");
            }

            List<Integer> booleans = paymentDetails.stream().map(HouseOfflinePaymentDetails::getStatus).filter(mStatus -> mStatus != 0).collect(Collectors.toList());
            if (booleans.size() > 0) {
                return ResultBean.failedResultOfParamWithMsg("凭证已审核不可重复审核！");
            }

            for (HouseOfflinePaymentDetails detail : paymentDetails) {
                // 审核类型 0通过 1不通过
                if (status == 0) {
                    Integer accountType = detail.getAccountType();

                    if (accountType == 0) {
                        HouseRemainingRelation relation = houseRemainingRelationRepository.findByOrgIdAndHouseId(detail.getOrgId(), detail.getHouseId());
                        if (relation == null) {
                            return ResultBean.failedResultOfParamWithMsg("未查询到房屋账户 请联系管理员添加账户！");
                        }
                        Optional<HouseRemaining> houseRemaining = houseRemainingRepository.findById(relation.getRemainingId());
                        if (!houseRemaining.isPresent()) {
                            return ResultBean.failedResultOfParamWithMsg("未查询到房屋账户 请联系管理员添加账户！");
                        }

                        HouseRemaining remaining = houseRemaining.get();
                        remaining.setBalanceFee(remaining.getBalanceFee() + detail.getOperateMoney());
                        remaining.setLastUpdateTime(date);
                        houseRemainingRepository.save(remaining);

                        // 余额操作明细
                        HouseRemainingRecord record = new HouseRemainingRecord();
                        record.setRemainingId(remaining.getId());
                        record.setOperateMoney(detail.getOperateMoney());
                        record.setOperatorId(userId);
                        record.setOperateName(userName);
                        record.setLastUpdateTime(date);
                        // 操作状态: 1成功 2失败
                        record.setUpdateStatus(1);
                        record.setCause("线下缴费充值");
                        // 1充值 2扣减 3退款
                        record.setOperateStatus(1);
                        // 账单类型:1租金押金 2其他费用 3充值
                        record.setBillStatus(5);
                        // 1正常 2已删除
                        record.setStatus(1);
                        houseRemainingRecordRepository.save(record);

                        // 充值后扣减账单
                        wxPayService.billDeduction(remaining);
                    }

                    // 单位账户
                    if (accountType == 1) {

                        if (detail.getRemainingId() == null) {
                            return ResultBean.failedResultOfParamWithMsg("参数有误");
                        }

                        Optional<DepartmentRemaining> byId = departmentRemainingRepository.findById(detail.getRemainingId());
                        if (!byId.isPresent()) {
                            ResultBean.failedResultWithMsg("账户不存在");
                        }

                        DepartmentRemaining departmentRemaining = byId.get();
                        departmentRemaining.setBalanceFee(departmentRemaining.getBalanceFee() + detail.getOperateMoney());
                        departmentRemaining.setLastUpdateTime(date);
                        departmentRemainingRepository.save(departmentRemaining);


                        DepartmentRemainingRecord record = new DepartmentRemainingRecord();
                        record.setHouseId(detail.getHouseId());
                        record.setRemainingId(departmentRemaining.getId());
                        record.setOperateMoney(detail.getOperateMoney());
                        record.setOperatorId(userId);
                        record.setUpdateTime(date);
                        record.setUpdateStatus(1);
                        record.setCause("线下缴费充值");
                        record.setOperateStatus(1);
                        record.setBillStatus(0);
                        record.setStatus(1);
                        departmentRemainingRecordRepository.save(record);

                    }

                    // 凭证状态  0未审核 1已通过 2未通过
                    detail.setStatus(1);
                } else {
                    // 凭证状态 0未审核 1已通过 2未通过
                    detail.setStatus(2);
                }

                detail.setOperatorId(userId);
                detail.setLastUpdateTime(date);


                houseOfflinePaymentDetailsRepository.save(detail);
            }

            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }


    /**
     * 账户管理-缴费凭证管理 缴费凭证提交
     *
     * @param accessToken
     * @param vo
     * @return
     */
    public ResultBean<Object> addVoucher(String accessToken, VoucherVo vo) {
        log.info("AccountManageService  addVoucher VoucherVo={}", vo);
        try {
            // 校验登录信息
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null)
                return ResultBean.failedResultOfToken();

            if (vo.getOperateMoney() == null || vo.getOperateMoney().doubleValue() < 0) {
                return ResultBean.failedResultOfParamWithMsg("缴费金额有误");
            }

            String userId = token.getId();
            Long orgId = token.getEnterpriseId();

            User user = userRepository.findById(userId);
            if (user == null) {
                return ResultBean.failedResultOfParamWithMsg("当前登录用户不存在");
            }
            String imgs = "";


            List<String> paymentVoucher = vo.getPaymentVoucher();
            if (!paymentVoucher.isEmpty()) {
                imgs = String.join(",", paymentVoucher);
            }
            Integer accountType = vo.getAccountType();

            if (accountType == null) {
                return ResultBean.failedResultOfParamWithMsg("缴费账户类型有误");
            }

            // 房屋缴费
            if (accountType == 0) {
                if (StringUtils.isEmpty(vo.getHouseId())) {
                    return ResultBean.failedResultOfParamWithMsg("房屋id有误");
                }

                HouseRemainingRelation relation = houseRemainingRelationRepository.findByOrgIdAndHouseId(orgId, vo.getHouseId());
                if (relation == null) {
                    return ResultBean.failedResultOfParamWithMsg("该房屋暂无账户，无法缴费");
                }

                Optional<HouseRemaining> remainingRepositoryById = houseRemainingRepository.findById(relation.getRemainingId());
                if (!remainingRepositoryById.isPresent()) {
                    return ResultBean.failedResultOfParamWithMsg("该房屋暂无账户，无法缴费");
                }

                Optional<House> byId = houseRepository.findById(vo.getHouseId());
                if (!byId.isPresent()) {
                    return ResultBean.failedResultOfParamWithMsg("房屋不存在");
                }
                HouseRemaining remaining = remainingRepositoryById.get();
                Date date = new Date();


                // 缴费凭证明细
                HouseOfflinePaymentDetails details = new HouseOfflinePaymentDetails();
                // 审核状态 ：0未审核 1已通过 2未通过
                details.setStatus(0);
                details.setHouseId(vo.getHouseId());
                details.setOrgId(orgId);
                details.setMatchUserId(remaining.getMatchUserId());
                details.setRemainingId(remaining.getId());
                String fen = ConvertUtils.yuanToFen(vo.getOperateMoney().toPlainString());
                details.setOperateMoney(Integer.parseInt(fen));
                details.setCreateTime(date);
                details.setPaymentVoucher(imgs);
                details.setVoucherNumber(vo.getVoucherNumber());
                details.setCreateUserId(userId);
                // 账户类型： 0房屋账户 1单位账户
                details.setAccountType(0);
                houseOfflinePaymentDetailsRepository.save(details);
            }

            if (accountType == 1) {

                if (vo.getDepRemainingId() == null) {
                    return ResultBean.failedResultOfParamWithMsg("参数有误");
                }

                DepartmentRemaining departmentRemaining = departmentRemainingRepository.findByDepIdAndOrgId(vo.getDepRemainingId(), orgId);
                if (departmentRemaining == null) {
                    return ResultBean.failedResultWithMsg("账户不存在");
                }
                Date date = new Date();


                // 缴费凭证明细
                HouseOfflinePaymentDetails details = new HouseOfflinePaymentDetails();
                // 审核状态 ：0未审核 1已通过 2未通过
                details.setStatus(0);
                details.setHouseId(vo.getHouseId());
                details.setOrgId(orgId);
                details.setMatchUserId(departmentRemaining.getDepId().toString());
                details.setRemainingId(departmentRemaining.getId());
                String fen = ConvertUtils.yuanToFen(vo.getOperateMoney().toPlainString());
                details.setOperateMoney(Integer.parseInt(fen));
                details.setCreateTime(date);
                details.setPaymentVoucher(imgs);
                details.setVoucherNumber(vo.getVoucherNumber());
                details.setCreateUserId(userId);
                // 账户类型： 0房屋账户 1单位账户
                details.setAccountType(accountType);
                houseOfflinePaymentDetailsRepository.save(details);
            }
            return ResultBean.successfulResult("提交成功");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 退租管理-已退租列表
     *
     * @param accessToken
     * @param residenceCommunityId 小区
     * @param buildingNum          楼宇
     * @param unit                 单元
     * @param roomNumber           房号
     * @param name                 承租人
     * @param refundStatus         退费状态  0未退款 1已退款
     * @return
     */
   /* public ResultBean<ApiData<RetiredVo>> retiredLeaseList(String accessToken, String residenceCommunityId, Long buildingNum, Long unit, String roomNumber,
                                               String name, Integer pageNumber, Integer pageSize, Long refundStatus) {

        try {
            ApiData<RetiredVo> apiData = new ApiData<>();
            List<RetiredVo> data = new ArrayList<>();

            //校验登录信息
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null)
                return ResultBean.failedResultOfToken();

            //用户对应房屋
            List<Map<String, Object>> communityList = appCommunityService.findCommunity(accessToken).getResultData();


            String retiredSql = "SELECT\n" +
                    "\tr.id AS remainingId,\n" +
                    "\tsc.id AS residenceCommunityId,\n" +
                    "\tsc.`name` AS residenceCommunityName,\n" +
                    "\tscb.id AS buildingNum,\n" +
                    "\tscb.`name` AS buildingNumName,\n" +
                    "\tscbu.id AS unit,\n" +
                    "\tscbu.`name` AS unitName,\n" +
                    "\th.room_number AS roomNumber,\n" +
                    "\tchu.`name` AS matchUserName,\n" +
                    "\tchu.user_id AS matchUserId,\n" +
                    "\tr.balance_fee  AS cost,\n" +
                    "IF\n" +
                    "\t( r.`status` = 5, 0, 1 ) AS retiredStatus,\n" +
                    "\trr.last_update_time AS retiredTime,\n" +
                    "\trr.operator_id AS operatorId,\n" +
                    "\tmuh.start_date AS startDate,\n" +
                    "\tmuh.end_date AS endDate\n" +
                    "\n" +
                    "FROM\n" +
                    "\t`saas_house_remaining` r\n" +
                    "\tLEFT JOIN `saas_house_remaining_record` rr ON rr.remaining_id = r.id and rr.operate_status = 3 \n" +
                    "\tLEFT JOIN saas_house h ON r.house_id = h.id\n" +
                    "\tLEFT JOIN saas_community sc ON h.residence_community_id = sc.id\n" +
                    "\tLEFT JOIN saas_community_build scb ON h.building_num = scb.id\n" +
                    "\tLEFT JOIN saas_community_build_unit scbu ON h.unit = scbu.id\n" +
                    "\tLEFT JOIN saas_community_house_user chu ON r.house_id = chu.community_house_id and chu.type = 1\n" +
                    "\tLEFT JOIN m_match_user_house muh ON r.house_id = muh.house_id \n" +
                    "WHERE\n" +
                    "\t1 = 1 ";

            StringBuilder where = new StringBuilder();
            List<Object> age = new ArrayList<>();
            where.append(" and r.status IN ( 5 , 6)");
            //登录类型
            Integer loginType = token.getLoginType();
            String userId = token.getId();

            if (loginType == 1) {//企业用户
                //企业用户拼接小区id
                if (communityList != null && !communityList.isEmpty()) {
                    StringBuilder communityIds = new StringBuilder("");
                    for (Map<String, Object> map : communityList) {
                        communityIds.append("'" + map.get("communityId") + "'").append(",");
                    }
                    String communityIdsStr = communityIds.toString().substring(0, communityIds.toString().lastIndexOf(","));

                    retiredSql += "  AND h.residence_community_id IN (  " + communityIdsStr + " )  ";
                } else {
                    retiredSql += "  AND h.residence_community_id IN ( null )  ";
                }
            } else {//非企业用户
                //登录用户名下房屋
                List<String> houseIdList = communityService.getHouseIdList(userId);
                if (houseIdList.isEmpty()) {
                    return ResultBean.successfulResult(apiData);
                }

                //查名下管理房屋的成员
                StringBuilder houseIds = new StringBuilder("");
                for (String hId : houseIdList) {
                    houseIds.append("'" + hId + "'").append(",");
                }
                String houseIdsStr = houseIds.toString().substring(0, houseIds.toString().lastIndexOf(","));
                retiredSql += "  and h.residence_community_id IN (  " + houseIdsStr + " )  ";
            }

            //条件查询
            if (!StringUtils.isEmpty(residenceCommunityId)) {
                where.append(" and  h.residence_community_id = ? ");
                age.add(residenceCommunityId);
            }
            if (!StringUtils.isEmpty(roomNumber)) {
                where.append(" and  h.room_number = ? ");
                age.add(roomNumber);
            }

            if (buildingNum != null) {
                where.append(" and h.building_num = ? ");
                age.add(buildingNum);
            }

            if (unit != null) {
                where.append(" and h.unit = ? ");
                age.add(buildingNum);
            }

            if (!StringUtils.isEmpty(name)) {
                where.append(" and  chu.name  like '%" + name + "%' ");
            }
            if (refundStatus != null) {
                if (refundStatus == 0) {
                    where.append(" and r.status = 5 ");
                } else {
                    where.append(" and r.status = 6 ");
                }
            }
            // 查询总记录数
            String count = "select count(1) FROM (" + retiredSql + where + ") c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, age.toArray());
            if (total == 0) {
                apiData.setData(data);
                apiData.setTotal(total);
                return ResultBean.successfulResult(apiData);
            }



            age.add(pageSize);
            age.add(pageNumber * pageSize);

            data = jdbcTemplate.query(retiredSql + where + SQL_PAGE, new BeanPropertyRowMapper<>(RetiredVo.class), age.toArray());

            // 查询承租人名称
            List<String> ids = data.stream().filter(vo -> vo.getMatchUserId() != null)
                    .map(RetiredVo::getMatchUserId).distinct().collect(Collectors.toList());
            if (!ids.isEmpty()) {
                List<AppUser> appUsers = appUserRepository.findByIdOrEnterpriseIn(ids, ids);
                for (AppUser appUser : appUsers) {
                    for (RetiredVo vo : data) {
                        if (null != vo.getMatchUserId() && vo.getMatchUserName() ==null) {
                            if (vo.getMatchUserId().equals(appUser.getId())
                                    || vo.getMatchUserId().equals(appUser.getEnterpriseUserId())) {
                                vo.setMatchUserName(appUser.getName());
                            }
                        }
                    }
                }
            }
            // 查询小区名称
            List<String> residenceCommunityIds = data.stream().filter(vo -> vo.getResidenceCommunityId() != null)
                    .map(RetiredVo::getResidenceCommunityId).distinct().collect(Collectors.toList());
            if (!residenceCommunityIds.isEmpty()) {
                Map<String, String> map = communityRepository.findByIdIn(residenceCommunityIds).stream()
                        .collect(Collectors.toMap(Community::getId, Community::getName));
                if (!map.isEmpty()) {
                    data.forEach(vo -> vo.setResidenceCommunityName(map.get(vo.getResidenceCommunityId())));
                }
            }
            // 查询楼栋名称
            List<Long> buildingIds = data.stream().filter(vo -> vo.getBuildingNum() != null)
                    .map(RetiredVo::getBuildingNum).distinct().collect(Collectors.toList());
            if (!buildingIds.isEmpty()) {
                Map<Long, String> map = communityBuildRepository.findByIdIn(buildingIds).stream()
                        .collect(Collectors.toMap(CommunityBuild::getId, CommunityBuild::getName));
                if (!map.isEmpty()) {
                    data.forEach(vo -> vo.setBuildingNumName(map.get(vo.getBuildingNum())));
                }
            }
            // 查询单元名称
            List<Long> unitIds = data.stream().filter(vo -> vo.getUnit() != null).map(RetiredVo::getUnit)
                    .distinct().collect(Collectors.toList());
            if (!unitIds.isEmpty()) {
                Map<Long, String> map = communityBuildUnitRepository.findByIdIn(unitIds).stream()
                        .collect(Collectors.toMap(CommunityBuildUnit::getId, CommunityBuildUnit::getName));
                if (!map.isEmpty()) {
                    data.forEach(vo -> vo.setUnitName(map.get(vo.getUnit())));
                }
            }
            data.forEach(vo -> vo.setCost(ConvertUtils.fenToYuan(vo.getCost())));

            apiData.setData(data);
            apiData.setTotal(total);
            return ResultBean.successfulResult(apiData);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }
*/

    /**
     * 退租管理-退款
     *
     * @param accessToken
     * @param returnId    退费id
     * @return
     */
    @Transactional
    public ResultBean<Object> refund(String accessToken, Long returnId) {
        log.info("AccountManageService refund accessToken={},returnId={}", accessToken, returnId);
        try {

            // 校验登录信息
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null)
                return ResultBean.failedResultOfToken();

            if (returnId == null) {
                return ResultBean.failedResultOfParamWithMsg("参数有误");
            }

            Date date = new Date();
            User user = userRepository.findByMobile(token.getPhone());
            if (user == null) {
                return ResultBean.failedResultOfParamWithMsg("用户不存在");
            }


            Optional<HouseReturnPremium> houseReturnPremium = houseReturnPremiumRepository.findById(returnId);
            if (!houseReturnPremium.isPresent()) {
                return ResultBean.failedResultWithMsg("账户未找到");
            }
            HouseReturnPremium returnPremium = houseReturnPremium.get();
            if (returnPremium.getPaymentStatus() == 1) {
                return ResultBean.failedResultWithMsg("记录已处理，不可重复操作！");
            }
            returnPremium.setOperatorId(user.getId());
            // 缴费状态：0未处理 1已处理
            returnPremium.setPaymentStatus(1);
            returnPremium.setPaymentTime(date);
            houseReturnPremiumRepository.save(returnPremium);
            // 新增修改退租列表中的退租状态为已结清 xiaolong 20230313
            Long surrenderId = returnPremium.getSurrenderId();
            Optional<HouseSurrender> byId = houseSurrenderRepository.findById(surrenderId);
            if (byId.isPresent()) {
                HouseSurrender houseSurrender = byId.get();
                houseSurrender.setStatus(4);
                houseSurrenderRepository.save(houseSurrender);
            }

            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 账单列表 - 调整账单
     *
     * @param accessToken
     * @param vo
     * @return
     */
    @Transactional
    public ResultBean<Object> billAdjust(String accessToken, BillAdjustVo vo) {
        try {
            // 校验登录信息
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null)
                return ResultBean.failedResultOfToken();

            // 0账单审核 1缴费凭证审核
            Boolean flag = checkAuditor(accessToken, 0);
            if (!flag) {
                return ResultBean.failedResultWithMsg("审核未授权,请联系管理员授权");
            }

            if (vo.getBillId() == null || vo.getChargeType() == null || vo.getAdjustType() == null) {
                return ResultBean.failedResultOfParamWithMsg("参数有误");
            }
            Integer cost = Integer.valueOf(ConvertUtils.yuanToFen(vo.getCost().toPlainString()));
            if (vo.getCost() == null || cost <= 0) {
                return ResultBean.failedResultOfParamWithMsg("调整金额有误");
            }

            User user = userRepository.findByMobile(token.getPhone());
            if (user == null) {
                return ResultBean.failedResultWithMsg("当前登录用户未找到");
            }
            // 调整金额

            Integer chargeType = vo.getChargeType();
            Long billId = vo.getBillId();
            Integer adjustType = vo.getAdjustType();

            String chargeName = null;
            switch (chargeType) {  //  1水费 2电费 3物业费 4宽带费 5电视费 6煤气费 7暖气费 8租金 9押金
                case 1:
                    chargeName = "水费调整";
                    break;
                case 2:
                    chargeName = "电费调整";
                    break;
                case 3:
                    chargeName = "物业费调整";
                    break;
                case 4:
                    chargeName = "宽带费调整";
                    break;
                case 5:
                    chargeName = "电视费调整";
                    break;
                case 6:
                    chargeName = "燃气费调整";
                    break;
                case 7:
                    chargeName = "暖气费调整";
                    break;
                case 8:
                    chargeName = "租金调整";
                    break;
                case 9:
                    chargeName = "押金调整";
                    break;
            }

            // 补缴
            if (adjustType == 0) {
                // 租金押金
                if (chargeType == 8 || chargeType == 9) {
                    Optional<EstateRentBill> rent = estateRentBillRepository.findById(billId);
                    if (!rent.isPresent()) {
                        return ResultBean.failedResultWithMsg("账单不存在");
                    }
                    EstateRentBill rentBill = rent.get();


                    if (rentBill.getAdjustStatus() == 1) {
                        return ResultBean.failedResultWithMsg("账单已调整，请勿重复调整");
                    }
                    rentBill.setAdjustStatus(1);
                    estateRentBillRepository.save(rentBill);

                    // 生成调整账单
                    EstateAdjustBill adjustBill = new EstateAdjustBill();
                    adjustBill.setCommunityId(rentBill.getCommunityId());
                    // 账单状态 ： 0未完成 1已完成
                    adjustBill.setStatus(0);
                    //*调整类型： 0补缴 1退款
                    adjustBill.setAdjustType(0);
                    adjustBill.setBillId(rentBill.getId());
                    adjustBill.setHouseId(rentBill.getHouseId());
                    adjustBill.setBuildingNum(rentBill.getBuildingNum());
                    adjustBill.setUnit(rentBill.getUnit());
                    adjustBill.setRoomNumber(rentBill.getRoomNumber());
                    adjustBill.setOrgId(rentBill.getOrgId());
                    adjustBill.setMatchUserId(rentBill.getMatchUserId());
                    adjustBill.setAdjustCost(cost);
                    adjustBill.setCost(rentBill.getCost() + cost);
                    adjustBill.setOperatorId(user.getId());
                    // 账单类型 1：租金押金 2其他费用
                    adjustBill.setBillType(1L);
                    EstateAdjustBill adjustBill1 = estateAdjustBillRepository.save(adjustBill);

                    // 租金/押金 账单待办事项
                    propertyRentItem(rentBill.getHouseId(), adjustBill1.getId(), rentBill.getChargeType(), cost, user.getId(), rentBill);

                } else {
                    Optional<EstateExpenseBill> expense = estateExpenseBillRepository.findById(billId);
                    if (!expense.isPresent()) {
                        return ResultBean.failedResultWithMsg("账单不存在");
                    }
                    EstateExpenseBill expenseBill = expense.get();

                    if (expenseBill.getAdjustStatus() == 1) {
                        return ResultBean.failedResultWithMsg("账单已调整，请勿重复调整");
                    }
                    expenseBill.setAdjustStatus(1);
                    estateExpenseBillRepository.save(expenseBill);
                    // 生成调整账单
                    EstateAdjustBill adjustBill = new EstateAdjustBill();
                    adjustBill.setCommunityId(expenseBill.getCommunityId());
                    // 账单状态 ： 0未完成 1已完成
                    adjustBill.setStatus(0);
                    //*调整类型： 0补缴 1退款
                    adjustBill.setAdjustType(0);
                    adjustBill.setBillId(expenseBill.getId());
                    adjustBill.setHouseId(expenseBill.getHouseId());
                    adjustBill.setBuildingNum(expenseBill.getBuildingNum());
                    adjustBill.setUnit(expenseBill.getUnit());
                    adjustBill.setRoomNumber(expenseBill.getRoomNumber());
                    adjustBill.setOrgId(expenseBill.getOrgId());
                    adjustBill.setMatchUserId(expenseBill.getMatchUserId());
                    adjustBill.setAdjustCost(cost);
                    adjustBill.setCost(expenseBill.getCost() + cost);
                    adjustBill.setOperatorId(user.getId());
                    // 账单类型 1：租金押金 2其他费用
                    adjustBill.setBillType(2L);
                    EstateAdjustBill adjustBill1 = estateAdjustBillRepository.save(adjustBill);

                    // 租金/押金 账单待办事项
                    propertyOtherItem(expenseBill.getHouseId(), adjustBill1.getId(), expenseBill.getChargeType(), cost, user.getId(), expenseBill);
                }
            } else {
                // 租金/押金
                if (chargeType == 8 || chargeType == 9) {
                    Optional<EstateRentBill> rent = estateRentBillRepository.findById(billId);
                    if (!rent.isPresent()) {
                        return ResultBean.failedResultWithMsg("账单不存在");
                    }
                    EstateRentBill rentBill = rent.get();
                    if (rentBill.getAdjustStatus() == 1) {
                        return ResultBean.failedResultWithMsg("账单已调整，请勿重复调整");
                    }
                    if (rentBill.getCost() - cost < 0) {
                        return ResultBean.failedResultWithMsg("调整金额不得大于原账单金额");
                    }
                    rentBill.setAdjustStatus(1);
                    estateRentBillRepository.save(rentBill);
                    // 生成调整账单
                    EstateAdjustBill adjustBill = new EstateAdjustBill();
                    adjustBill.setCommunityId(rentBill.getCommunityId());
                    // 账单状态 ： 0未完成 1已完成
                    adjustBill.setStatus(1);
                    //*调整类型： 0补缴 1退款
                    adjustBill.setAdjustType(1);
                    adjustBill.setBillId(rentBill.getId());
                    adjustBill.setHouseId(rentBill.getHouseId());
                    adjustBill.setBuildingNum(rentBill.getBuildingNum());
                    adjustBill.setUnit(rentBill.getUnit());
                    adjustBill.setRoomNumber(rentBill.getRoomNumber());
                    adjustBill.setOrgId(rentBill.getOrgId());
                    adjustBill.setMatchUserId(rentBill.getMatchUserId());
                    adjustBill.setAdjustCost(cost);
                    adjustBill.setCost(rentBill.getCost() - cost);
                    adjustBill.setOperatorId(user.getId());
                    // 账单类型 1：租金押金 2其他费用
                    adjustBill.setBillType(1L);
                    EstateAdjustBill adjustBill1 = estateAdjustBillRepository.save(adjustBill);


                    String ruleId = rentBill.getRuleId();
                    // 账单生成规则
                    HouseExpenseBillRule rule = houseExpenseBillRuleRepository.findById(ruleId);
                    if (rule == null) {
                        return ResultBean.failedResultWithMsg("账单规则未找到");
                    }

                    // 余额账户
                    HouseRemainingRelation remainingRelation = houseRemainingRelationRepository.findByOrgIdAndHouseId(rule.getCollectionOrg(), rentBill.getHouseId());
                    if (remainingRelation == null) {
                        return ResultBean.failedResultWithMsg("余额账户不存在");
                    }
                    Optional<HouseRemaining> remaining = houseRemainingRepository.findById(remainingRelation.getRemainingId());
                    if (!remaining.isPresent()) {
                        return ResultBean.failedResultWithMsg("余额账户不存在");
                    }

                    HouseRemaining houseRemaining = remaining.get();
                    Integer cashPledge = houseRemaining.getCashPledge();


                    if (chargeType == 9) {

                        if (cashPledge < cost) {
                            return ResultBean.failedResultWithMsg("无法退款,押金账户余额不足");
                        }
                        BigDecimal sub = NumberUtil.sub(cashPledge, cost);
                        houseRemaining.setCashPledge(sub.intValue());
                    }
                    Integer balanceFee = houseRemaining.getBalanceFee();

                    houseRemaining.setBalanceFee(balanceFee + cost);
                    houseRemaining.setLastUpdateTime(new Date());
                    HouseRemaining save = houseRemainingRepository.save(houseRemaining);

                    // 余额操作记录
                    HouseRemainingRecord record = new HouseRemainingRecord();
                    record.setOperateName(user.getName());
                    record.setBillId(adjustBill1.getId());
                    record.setRemainingId(save.getId());
                    record.setOperateMoney(cost);
                    record.setOperatorId(user.getId());
                    record.setLastUpdateTime(new Date());
                    record.setUpdateStatus(1);
                    record.setCause(chargeName + "账单退款");
                    record.setOperateStatus(3);
                    record.setBillStatus(1);
                    record.setStatus(1);
                    houseRemainingRecordRepository.save(record);
                    // 余额变动待办事项
                    houseRemainingItem(rentBill.getHouseId(), rentBill.getMatchUserId(),
                            save.getId(), chargeType, cost, user.getId(), rule.getCollectionOrg(), chargeName);

                } else {
                    Optional<EstateExpenseBill> expense = estateExpenseBillRepository.findById(billId);
                    if (!expense.isPresent()) {
                        return ResultBean.failedResultWithMsg("账单不存在");
                    }
                    EstateExpenseBill expenseBill = expense.get();
                    if (expenseBill.getAdjustStatus() == 1) {
                        return ResultBean.failedResultWithMsg("账单已调整，请勿重复调整");
                    }
                    if (expenseBill.getCost() - cost < 0) {
                        return ResultBean.failedResultWithMsg("调整金额不得大于原账单金额");
                    }
                    expenseBill.setAdjustStatus(1);
                    estateExpenseBillRepository.save(expenseBill);
                    // 生成调整账单
                    EstateAdjustBill adjustBill = new EstateAdjustBill();


                    adjustBill.setCommunityId(expenseBill.getCommunityId());
                    // 账单状态 ： 0未完成 1已完成
                    adjustBill.setStatus(1);
                    //*调整类型： 0补缴 1退款
                    adjustBill.setAdjustType(1);
                    adjustBill.setBillId(expenseBill.getId());
                    adjustBill.setHouseId(expenseBill.getHouseId());
                    adjustBill.setBuildingNum(expenseBill.getBuildingNum());
                    adjustBill.setUnit(expenseBill.getUnit());
                    adjustBill.setRoomNumber(expenseBill.getRoomNumber());
                    adjustBill.setOrgId(expenseBill.getOrgId());
                    adjustBill.setMatchUserId(expenseBill.getMatchUserId());
                    adjustBill.setAdjustCost(cost);
                    adjustBill.setCost(expenseBill.getCost() - cost);
                    adjustBill.setOperatorId(user.getId());
                    // 账单类型 1：租金押金 2其他费用
                    adjustBill.setBillType(2L);
                    EstateAdjustBill adjustBill1 = estateAdjustBillRepository.save(adjustBill);


                    String ruleId = expenseBill.getRuleId();
                    // 账单生成规则
                    HouseExpenseBillRule rule = houseExpenseBillRuleRepository.findById(ruleId);
                    if (rule == null) {
                        return ResultBean.failedResultWithMsg("账单规则未找到");
                    }

                    // 余额账户
                    HouseRemainingRelation remainingRelation = houseRemainingRelationRepository.findByOrgIdAndHouseId(expenseBill.getOrgId(), expenseBill.getHouseId());
                    if (remainingRelation == null) {
                        return ResultBean.failedResultWithMsg("余额账户不存在");
                    }

                    Optional<HouseRemaining> remaining = houseRemainingRepository.findById(remainingRelation.getRemainingId());
                    if (!remaining.isPresent()) {
                        return ResultBean.failedResultWithMsg("余额账户不存在");
                    }

                    HouseRemaining houseRemaining = remaining.get();
                    Integer balanceFee = houseRemaining.getBalanceFee();
                    houseRemaining.setBalanceFee(balanceFee + cost);
                    houseRemaining.setLastUpdateTime(new Date());
                    HouseRemaining save = houseRemainingRepository.save(houseRemaining);

                    // 余额操作记录
                    HouseRemainingRecord record = new HouseRemainingRecord();
                    record.setOperateName(user.getName());
                    record.setBillId(adjustBill1.getId());
                    record.setRemainingId(save.getId());
                    record.setOperateMoney(cost);
                    record.setOperatorId(user.getId());
                    record.setLastUpdateTime(new Date());
                    record.setUpdateStatus(1);
                    record.setCause(chargeName + "账单退款");
                    record.setOperateStatus(3);
                    record.setBillStatus(1);
                    record.setStatus(1);
                    houseRemainingRecordRepository.save(record);
                    // 余额变动待办事项
                    houseRemainingItem(expenseBill.getHouseId(), expenseBill.getMatchUserId(),
                            save.getId(), chargeType, cost, user.getId(), rule.getCollectionOrg(), chargeName);
                }
            }
            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 扣减余额
     *
     * @param remainingId 余额id
     * @param billId      账单id
     * @param chargeType  扣款类型 1水费 2电费 3物业费 4宽带费 5电视费 6煤气费 7暖气费 8租金 9押金
     */
    //@Transactional
    /*public Integer deductionRemaining(Long remainingId, Long billId, Integer chargeType) {
        Integer flag = DeductionEnum.NOT_PAY.getValue();
        Optional<HouseRemaining> rem = houseRemainingRepository.findById(remainingId);
        if (!rem.isPresent()) {
            log.info("未查到余额账户 {}", remainingId);
            return flag;
        }
        HouseRemaining houseRemaining = rem.get();
        Integer balanceFee = houseRemaining.getBalanceFee();
        //操作金额
        Integer operateMoney = 0;
        BigDecimal remaining = new BigDecimal(balanceFee);
        final Date updateTime = new Date();
        //系统id
        String systemUser = redisService.getSystemUser();
        if (balanceFee <= 0) {
            log.info("余额不足 {}", remainingId);
            return flag;
        }
        Optional<EstateExpenseBill> expenseBill = estateExpenseBillRepository.findById(billId);
        if (expenseBill.isPresent()) {//其他费用
            EstateExpenseBill estateExpenseBill = expenseBill.get();
            Integer cost = estateExpenseBill.getSurplusCost();
            BigDecimal billCost = new BigDecimal(cost);
            operateMoney = cost;
            //账单费用扣减
            cost = Integer.parseInt(remaining.subtract(billCost).toString());
            estateExpenseBill.setSurplusCost(0);
            estateExpenseBill.setPaymentStatus(DeductionEnum.ALL_PAY.getValue());
            estateExpenseBill.setPaymentTime(updateTime);
            estateExpenseBill.setOperatorId(systemUser);
            estateExpenseBill.setPaymentChannel(PaymentTypeEnum.Remaining.getValue());
            estateExpenseBill.setPaymentStatus(RrentBillPaymentStatusTypeEnum.PAY.getValue());
            EstateExpenseBill saveBill = estateExpenseBillRepository.save(estateExpenseBill);

            //余额扣减
            houseRemaining.setBalanceFee(cost);
            houseRemaining.setLastUpdateTime(updateTime);
            HouseRemaining saveRemaining = houseRemainingRepository.save(houseRemaining);

            //余额操作记录
            HouseRemainingRecord record = new HouseRemainingRecord();
            record.setBillId(saveBill.getId());
            record.setRemainingId(saveRemaining.getId());
            record.setOperateMoney(operateMoney);
            record.setOperatorId(systemUser);
            record.setOperateName(SystemEnum.SYSTEM_USER_NAME.getValue());
            record.setLastUpdateTime(updateTime);
            record.setUpdateStatus(PaymentTypeEnum.SUCCESS.getValue());
            record.setCause(PaymentCauseEnum.SYSTEM_DEDUCTION.getValue());
            record.setOperateStatus(PaymentTypeEnum.BUCKLE.getValue());
            record.setBillStatus(PaymentTypeEnum.EXPENSE_BILL.getValue());
            //状态：1正常 2已删除
            record.setStatus(1);
            houseRemainingRecordRepository.save(record);


            //余额变动待办事项
            houseRemainingItem(saveBill.getHouseId(), saveBill.getMatchUserId(), saveRemaining.getId(), chargeType, operateMoney, systemUser, saveBill.getOrgId());
            //其他费用待办事项
            propertyOtherItem(saveBill.getId());

            flag = DeductionEnum.ALL_PAY.getValue();

        } else {//租金押金
            Optional<EstateRentBill> rentBill = estateRentBillRepository.findById(billId);
            EstateRentBill estateRentBill = rentBill.get();
            Integer cost = estateRentBill.getSurplusCost();
            BigDecimal billCost = new BigDecimal(cost);

            //1租金 2押金
            Integer rentBillChargeType = estateRentBill.getChargeType();
            if (rentBillChargeType == 1) {//租金
                operateMoney = cost;
                //账单费用扣减
                cost = Integer.parseInt(remaining.subtract(billCost).toString());
                estateRentBill.setSurplusCost(0);
                estateRentBill.setPaymentStatus(DeductionEnum.ALL_PAY.getValue());
                estateRentBill.setPaymentTime(updateTime);
                estateRentBill.setPaymentStatus(RrentBillPaymentStatusTypeEnum.PAY.getValue());
                EstateRentBill saveBill = estateRentBillRepository.save(estateRentBill);

                //余额扣减
                houseRemaining.setBalanceFee(cost);
                houseRemaining.setLastUpdateTime(updateTime);
                HouseRemaining saveRemaining = houseRemainingRepository.save(houseRemaining);

                //余额操作记录
                HouseRemainingRecord record = new HouseRemainingRecord();
                record.setBillId(saveBill.getId());
                record.setRemainingId(saveRemaining.getId());
                record.setOperateMoney(operateMoney);
                record.setOperatorId(systemUser);
                record.setOperateName(SystemEnum.SYSTEM_USER_NAME.getValue());
                record.setLastUpdateTime(updateTime);
                record.setUpdateStatus(PaymentTypeEnum.SUCCESS.getValue());
                record.setCause(PaymentCauseEnum.SYSTEM_DEDUCTION.getValue());
                record.setOperateStatus(PaymentTypeEnum.BUCKLE.getValue());
                record.setBillStatus(PaymentTypeEnum.RENT_BILL.getValue());
                //状态：1正常 2已删除
                record.setStatus(1);
                houseRemainingRecordRepository.save(record);

                //余额变动待办事项
                houseRemainingItem(saveBill.getHouseId(), saveBill.getMatchUserId(), saveRemaining.getId(), chargeType, operateMoney, systemUser, saveBill.getOrgId());
                //租金/押金待办事项
                propertyRentItem(saveBill.getId());
                flag = DeductionEnum.ALL_PAY.getValue();

            } else {
                //押金
                operateMoney = cost;
                //账单费用扣减
                cost = Integer.parseInt(remaining.subtract(billCost).toString());
                estateRentBill.setSurplusCost(0);
                estateRentBill.setPaymentStatus(DeductionEnum.ALL_PAY.getValue());
                estateRentBill.setPaymentTime(updateTime);
                estateRentBill.setPaymentStatus(RrentBillPaymentStatusTypeEnum.PAY.getValue());
                EstateRentBill saveBill = estateRentBillRepository.save(estateRentBill);

                //余额扣减
                houseRemaining.setBalanceFee(cost);
                houseRemaining.setCashPledge(operateMoney);
                houseRemaining.setLastUpdateTime(updateTime);
                HouseRemaining saveRemaining = houseRemainingRepository.save(houseRemaining);

                //余额操作记录
                HouseRemainingRecord record = new HouseRemainingRecord();
                record.setBillId(saveBill.getId());
                record.setRemainingId(saveRemaining.getId());
                record.setOperateMoney(operateMoney);
                record.setOperatorId(systemUser);
                record.setOperateName(SystemEnum.SYSTEM_USER_NAME.getValue());
                record.setLastUpdateTime(updateTime);
                record.setUpdateStatus(PaymentTypeEnum.SUCCESS.getValue());
                record.setCause(PaymentCauseEnum.SYSTEM_DEDUCTION.getValue());
                record.setOperateStatus(PaymentTypeEnum.BUCKLE.getValue());
                record.setBillStatus(PaymentTypeEnum.DEPOSIT_BILL.getValue());
                //状态：1正常 2已删除
                record.setStatus(1);
                houseRemainingRecordRepository.save(record);

                //余额变动待办事项
                houseRemainingItem(saveBill.getHouseId(), saveBill.getMatchUserId(), saveRemaining.getId(), chargeType, operateMoney, systemUser, saveBill.getOrgId());
                //租金/押金待办事项
                propertyRentItem(saveBill.getId());
                flag = DeductionEnum.ALL_PAY.getValue();

            }

        }
        return flag;
    }*/

    /**
     * 余额变动待办事项
     *
     * @param houseId     房屋ID
     * @param matchUserId 承租人ID
     * @param remainingId 余额ID
     * @param chargeType  扣款类型 1水费 2电费 3物业费 4宽带费 5电视费 6煤气费 7暖气费 8租金 9押金
     * @param cost        金额
     * @param operatorId  操作人ID
     * @param orgId       收款机构ID
     */
    public void houseRemainingItem(String houseId, String matchUserId, Long remainingId, Integer chargeType, Integer cost, String operatorId, Long orgId, String chargeName) {
        String yuan = ConvertUtils.fenToYuan(String.valueOf(cost));

//        String sql="select * from (\n" +
//                "select a.mobile as mobile ,a.community_house_id as houseId  , a.user_id as userId  from  saas_community_house_user a\n" +
//                "where   a.status = 1 \n" +
//                "UNION\n" +
//                "select b.phone as mobile , a.house_id as houseId , a.match_user_id as userId from   saas_house_match_user a \n" +
//                "LEFT JOIN saas_app_user b on b.id= a.match_user_id\n" +
//                "where 1=1\n" +
//                "UNION \n" +
//                "select b.mobile as mobile , a.house_id as houseId , c.id as userId from   saas_house_match_user a \n" +
//                "LEFT JOIN saas_house_eligible_apply_cohabit b on b.apply_id= a.apply_id\n" +
//                "LEFT JOIN saas_app_user c on c.phone = b.mobile \n" +
//                "where 1=1 and b.mobile is not null \n" +
//                ") t1 where t1.houseId ='"+houseId+"' ";

        /**
         * qixi
         * 2022-12-28 11:32
         * 余额变动承租人和已授权账单的同住人可见
         *
         */
        String sql = "select * from (select a.mobile as mobile ,a.community_house_id as houseId  , a.user_id as userId  " +
                "from  saas_community_house_user a\n" +
                "where a.status = 1 and a.type = 1  or (a.type = 2 and a.account_status = 1)\n" +
                "UNION\n" +
                "select b.phone as mobile , a.house_id as houseId , a.match_user_id as userId from   saas_house_match_user a\n" +
                "LEFT JOIN saas_app_user b on b.id= a.match_user_id\n" +
                "where 1=1\n" +
                ") t1 where t1.houseId ='" + houseId + "' ";


        String where = " and 1=1 ";

        List<CommunityHouseUser> CommunityHouseUserList = jdbcTemplate.query(sql + where, new BeanPropertyRowMapper<>(CommunityHouseUser.class));

        CommunityHouseUserList = CommunityHouseUserList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(CommunityHouseUser::getMobile))), ArrayList::new));
        for (CommunityHouseUser communityHouseUser : CommunityHouseUserList) {
            // 账单扣款余额变动
            BacklogItem backlogItem = new BacklogItem();
            backlogItem.setHouseId(houseId);
            backlogItem.setOrgId(orgId);
            backlogItem.setType(BacklogItemTypeEnum.REMAINING_CHANGE.getValue());
            backlogItem.setTitle("余额变动");
            backlogItem.setContent(chargeName + "账单，系统退款：" + yuan + "元");
            backlogItem.setBusinessStatus("待查看");
            backlogItem.setHandleStatus(0);
            backlogItem.setOperatorId(operatorId);// 操作人id
            backlogItem.setMatchUserId(matchUserId);
            backlogItem.setPhone(communityHouseUser.getMobile());
            backlogItem.setCreateTime(new Date());
            BacklogItem save = backlogItemRepository.save(backlogItem);

            BacklogItemHouseRemaining houseRemaining = new BacklogItemHouseRemaining();
            houseRemaining.setBacklogItemId(save.getId());
            houseRemaining.setRemainingId(remainingId);
            backlogItemHouseRemainingRepository.save(houseRemaining);

        }
    }

    /**
     * 非公租房租金/押金待办事项
     *
     * @param houseId        房屋ID
     * @param rentBillId     账单ID
     * @param billChargeType 收费项目:1租金 2押金
     * @param cost           金额
     * @param operatorId     操作人
     */
    public void propertyRentItem(String houseId, Long rentBillId, Integer billChargeType, Integer cost, String operatorId, EstateRentBill rentBill) {

        String yuan = ConvertUtils.fenToYuan(String.valueOf(cost));
        String chargeName = billChargeType == 1 ? "租金调整" : "押金调整";

        String sql = "select * from (\n" +
                "select a.mobile as mobile ,a.community_house_id as houseId  , a.user_id as userId  from  saas_community_house_user a\n" +
                "where   a.status = 1 and a.account_status = 1 \n" +
                "UNION\n" +
                "select b.phone as mobile , a.house_id as houseId , a.match_user_id as userId from   saas_house_match_user a \n" +
                "LEFT JOIN saas_app_user b on b.id= a.match_user_id\n" +
                "where 1=1\n" +
                "UNION \n" +
                "select b.mobile as mobile , a.house_id as houseId , c.id as userId from   saas_house_match_user a \n" +
                "LEFT JOIN saas_house_eligible_apply_cohabit b on b.apply_id= a.apply_id\n" +
                "LEFT JOIN saas_app_user c on c.phone = b.mobile \n" +
                "where 1=1 and b.mobile is not null" +
                ") t1 where t1.houseId ='" + houseId + "' ";

        String where = " and 1=1 ";
        if (org.apache.commons.lang3.StringUtils.isNotBlank(rentBill.getMatchUserId())) {
            where = " or t1.userId = '" + rentBill.getMatchUserId() + "'";
        }

        List<CommunityHouseUser> CommunityHouseUserList = jdbcTemplate.query(sql + where, new BeanPropertyRowMapper<>(CommunityHouseUser.class));

        CommunityHouseUserList = CommunityHouseUserList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(CommunityHouseUser::getMobile))), ArrayList::new));

        for (CommunityHouseUser communityHouseUser : CommunityHouseUserList) {
            AppUser appUser = appUserRepository.findByPhone(communityHouseUser.getMobile());

            // 生成非公租房租金/押金待办事项
            BacklogItem backlogItem = new BacklogItem();
            backlogItem.setHouseId(houseId);
            backlogItem.setType(BacklogItemTypeEnum.PROPERTY_BILL_RENT.getValue());
            backlogItem.setTitle(chargeName + "账单待缴费");
            backlogItem.setContent(chargeName + "账单，请尽快缴费");
            backlogItem.setBusinessStatus("待缴费");
            backlogItem.setHandleStatus(0);
            backlogItem.setOperatorId(operatorId);// 操作人id
            if (appUser != null) {
                backlogItem.setMatchUserId(appUser.getId());
            }
            backlogItem.setPhone(communityHouseUser.getMobile());
            backlogItem.setCreateTime(new Date());
            BacklogItem save = backlogItemRepository.save(backlogItem);

            BacklogItemPropertyRentBill PropertyRentBill = new BacklogItemPropertyRentBill();
            PropertyRentBill.setBacklogItemId(save.getId());
            if (appUser != null) {
                PropertyRentBill.setMatchUserId(appUser.getId());
            }

            if (billChargeType == 1) {
                PropertyRentBill.setRentBillId(rentBillId);// 租金账单id
            } else {
                PropertyRentBill.setDepositBillId(rentBillId);// 押金账单id
            }
            backlogItemPropertyRentBillRepository.save(PropertyRentBill);
            // 账单生成短信
            smsService.sendTemplateSmsWithData(communityHouseUser.getMobile(), smsConfig.getBillTemplateCode(), new String[]{chargeName, yuan});
        }

    }

    /**
     * 非公租房其他费用账单待办事项
     *
     * @param houseId        房屋ID
     * @param rentBillId     账单ID
     * @param billChargeType 账单类型
     * @param cost           金额
     * @param operatorId     操作人
     */
    public void propertyOtherItem(String houseId, Long rentBillId, Integer billChargeType, Integer cost, String operatorId, EstateExpenseBill expenseBill) {
        String yuan = ConvertUtils.fenToYuan(String.valueOf(cost));
        String chargeName = null;
        switch (billChargeType) {  // 1水费 2电费 3物业费 4宽带费 5电视费 6煤气费 7暖气费
            case 1:
                chargeName = "水费调整";
                break;
            case 2:
                chargeName = "电费调整";
                break;
            case 3:
                chargeName = "物业费调整";
                break;
            case 4:
                chargeName = "宽带费调整";
                break;
            case 5:
                chargeName = "电视费调整";
                break;
            case 6:
                chargeName = "燃气费调整";
                break;
            case 7:
                chargeName = "暖气费";
                break;
        }

//        String sql="select * from (\n" +
//                "select a.mobile as mobile ,a.community_house_id as houseId  , a.user_id as userId  from  saas_community_house_user a\n" +
//                "where   a.status = 1 \n" +
//                "UNION\n" +
//                "select b.phone as mobile , a.house_id as houseId , a.match_user_id as userId from   saas_house_match_user a \n" +
//                "LEFT JOIN saas_app_user b on b.id= a.match_user_id\n" +
//                "where 1=1\n" +
//                "UNION \n" +
//                "select b.mobile as mobile , a.house_id as houseId , c.id as userId from   saas_house_match_user a \n" +
//                "LEFT JOIN saas_house_eligible_apply_cohabit b on b.apply_id= a.apply_id\n" +
//                "LEFT JOIN saas_app_user c on c.phone = b.mobile \n" +
//                "where 1=1 and b.mobile is not null \n" +
//                ") t1 where t1.houseId ='"+houseId+"' ";

        /**
         * xin
         * 2022-09-20 13:42
         * 账单审核后只有承租人能收到短信
         */
        String sql = "select * from (\n" +
                "select a.mobile as mobile ,a.community_house_id as houseId  , a.user_id as userId  from  saas_community_house_user a\n" +
                "where   a.status = 1 and   a.type = 1\n" +
                "UNION\n" +
                "select b.phone as mobile , a.house_id as houseId , a.match_user_id as userId from   saas_house_match_user a\n" +
                "LEFT JOIN saas_app_user b on b.id= a.match_user_id\n" +
                "where 1=1\n" +
                ") t1 where t1.houseId ='" + houseId + "' ";


        String where = " and 1=1 ";
        if (StringUtils.isNotBlank(expenseBill.getMatchUserId())) {
            where = " or t1.userId = '" + expenseBill.getMatchUserId() + "'";
        }

        List<CommunityHouseUser> CommunityHouseUserList = jdbcTemplate.query(sql + where, new BeanPropertyRowMapper<>(CommunityHouseUser.class));

        CommunityHouseUserList = CommunityHouseUserList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(CommunityHouseUser::getMobile))), ArrayList::new));
        for (CommunityHouseUser communityHouseUser : CommunityHouseUserList) {
            AppUser appUser = appUserRepository.findByPhone(communityHouseUser.getMobile());

            // 非公租房其他费用账单待办事项
            BacklogItem backlogItem = new BacklogItem();
            backlogItem.setHouseId(houseId);
            backlogItem.setType(BacklogItemTypeEnum.PROPERTY_OTHER_BILL.getValue());
            backlogItem.setTitle(chargeName + "账单待缴费");
            backlogItem.setContent(chargeName + "账单，请尽快缴费");
            backlogItem.setBusinessStatus("待缴费");
            backlogItem.setHandleStatus(0);
            backlogItem.setOperatorId(operatorId);// 操作人id
            if (appUser != null) {
                backlogItem.setMatchUserId(appUser.getId());
            }
            backlogItem.setPhone(communityHouseUser.getMobile());
            backlogItem.setCreateTime(new Date());
            BacklogItem save = backlogItemRepository.save(backlogItem);

            BacklogItemPropertyOtherBill propertyOtherBill = new BacklogItemPropertyOtherBill();
            propertyOtherBill.setBacklogItemId(save.getId());
            propertyOtherBill.setBillId(rentBillId);

            backlogItemPropertyOtherBillRepository.save(propertyOtherBill);
            // 账单生成短信
            smsService.sendTemplateSmsWithData(communityHouseUser.getMobile(), smsConfig.getBillTemplateCode(), new String[]{chargeName, yuan});

        }

    }

    /**
     * 判断是否超过24小时
     *
     * @param date1 开始时间
     * @return boolean
     * @throws Exception
     */
    public static Integer judgmentDate(String date1) throws Exception {
        if (org.apache.commons.lang3.StringUtils.isBlank(date1)) {
            return 0;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Date start = sdf.parse(date1);

        Date end = sdf.parse(sdf.format(new Date()));

        long cha = end.getTime() - start.getTime();

        if (cha < 0) {

            return 1;

        }

        double result = cha * 1.0 / (1000 * 60 * 60);

        if (result < 24) {

            return 1;

        } else {

            return 1;

        }

    }

    /**
     * 账户管理 - 个人/单位承租人 账户列表
     *
     * @param accessToken
     * @param pageNumber
     * @param pageSize
     * @param residenceCommunityId 小区id
     * @param buildingNum          楼栋id
     * @param unit                 单元id
     * @param roomNumber           房号
     * @param name                 承租人
     * @param status               账户状态
     * @param orgId                机构id
     * @param accountType          账户类型 0个人承租人 1单位承租人
     * @return
     */
    public ResultBean<ApiData<RemainingAccountVo>> accountList(String accessToken, Integer pageNumber, Integer pageSize, String residenceCommunityId,
                                                               Long buildingNum, Long unit, String roomNumber, String name, Integer status, Long orgId, Integer accountType) {
        log.info("AccountManageService refund accountList={},orgId={}", accessToken, orgId);
        try {
            ApiData<RemainingAccountVo> data = new ApiData<>();

            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }

            if (orgId == null || accountType == null) {
                return ResultBean.failedResultOfParamWithMsg("参数有误");
            }

            String remSql = "select r.id as remainingId ,r.type as type, h.residence_community_id as communityId , h.`building_num` AS buildingNum,h.`unit` as unit ,\n" +
                    "h.`room_number` AS roomNumber,r.match_user_id AS matchUserId ,u.name as matchUserName, r.balance_fee as balanceFee ,r.cash_pledge as cashPledge ,r.`status` as remainingStatus ,h.id as houseId \n" +
                    "FROM saas_house_remaining_relation rr \n" +
                    "LEFT JOIN saas_house_remaining r ON rr.remaining_id = r.id \n" +
                    "LEFT JOIN saas_house  h ON rr.house_id = h.id\n" +
                    "LEFT JOIN  saas_community_house_user u  ON u.`community_house_id` = rr.house_id and u.status=1 and u.type=1\n";


            List<Object> args = new ArrayList<>();
            StringBuilder where = new StringBuilder(" WHERE 1 = 1 \n");

            String offsets = "   LIMIT ? OFFSET ? ";

            // 条件查询
            if (StringUtils.isNotBlank(residenceCommunityId)) {
                where.append("  AND  h.residence_community_id = ?  \n");
                args.add(residenceCommunityId);
            }
            if (buildingNum != null) {
                where.append("  AND  h.building_num = ?  \n");
                args.add(buildingNum);
            }
            if (unit != null) {
                where.append("  AND  h.unit = ?  \n");
                args.add(unit);
            }
            if (StringUtils.isNotBlank(roomNumber)) {
                where.append("  AND  h.room_number = ?  \n");
                args.add(roomNumber);
            }

            if (StringUtils.isNotBlank(name)) {
                where.append("  AND  u.name  like ?   \n");
                args.add("%" + name + "%");
            }
            if (status != null) {
                where.append("  AND  r.status  = ?   \n");
                args.add(status);
            }
            if (orgId != null) {
                where.append("  AND  r.org_id  = ?   \n");
                args.add(orgId);
            }
            if (accountType != null) {
                if (accountType == 0) {
                    where.append("  AND  r.type  = 1   \n");
                } else {
                    where.append("  AND  r.type  = 2   \n");
                }
            }


            // 统计总数
            String count = "select count(1) FROM (" + remSql + where + ") c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, args.toArray());
            if (total == 0) {
                return ResultBean.successfulResult(null);
            }

            // 查询分页数据
            where.append("  ORDER BY ").append(" r.create_time desc ").append(" \n").append(offsets);
            args.add(pageSize);
            args.add(pageNumber * pageSize);

            List<RemainingAccountVo> vos = jdbcTemplate.query(remSql + where, new BeanPropertyRowMapper<>(RemainingAccountVo.class), args.toArray());
            log.info(remSql + where + args.toArray());
            vos.forEach(m -> {
                if (StringUtils.isNotBlank(m.getCommunityId())) {
                    Optional<Community> communityOptional = communityRepository.findById(m.getCommunityId());
                    // 获取小区名称
                    if (communityOptional.isPresent()) {
                        Community community = communityOptional.get();
                        m.setCommunityName(community.getName());
                    }
                }

                if (m.getBuildingNum() != null) {
                    // 获取楼栋名称
                    Optional<CommunityBuild> communityBuildOptional = communityBuildRepository.findById(m.getBuildingNum());
                    if (communityBuildOptional.isPresent()) {
                        CommunityBuild communityBuild = communityBuildOptional.get();
                        m.setBuildingNumName(communityBuild.getName());
                    }
                }
                // 获取单元名称
                if (m.getUnit() != null) {
                    Optional<CommunityBuildUnit> communityBuildUnitOptional = communityBuildUnitRepository.findById(m.getUnit());
                    if (communityBuildUnitOptional.isPresent()) {
                        CommunityBuildUnit communityBuildUnit = communityBuildUnitOptional.get();
                        m.setUnitName(communityBuildUnit.getName());
                    }
                }
                String matchUserId = m.getMatchUserId();
                // 1个人承租人 2单位承租人 承租人名
                if (m.getType() == 2) {
                    User id = userRepository.findById(matchUserId);
                    if (id != null) {
                        List<UserDepartmentRef> byUserId = userDepartmentRefRepository.findByUserId(id.getId());
                        if (!byUserId.isEmpty()) {
                            Long depId = byUserId.get(0).getDepId();
                            Optional<Department> byId = departmentRepository.findById(depId);
                            if (byId.isPresent()) {
                                Department department = byId.get();
                                m.setMatchUserName(department.getName());
                            }
                        }
                    }
                } else if (StrUtil.isBlank(m.getMatchUserName())) {
                    if (StringUtils.isNotBlank(matchUserId)) {
                        List<MatchUser> matchUserList = matchUserRepository.findByUserId(matchUserId);
                        if (CollectionUtil.isNotEmpty(matchUserList)) {
                            MatchUser matchUser = matchUserList.get(0);
                            m.setMatchUserName(matchUser.getName());
                        }
                    }
                }

                m.setBalanceFee(ConvertUtils.fenToYuan(m.getBalanceFee()));
                m.setCashPledge(ConvertUtils.fenToYuan(m.getCashPledge()));
                m.setOrgId(orgId);
            });

            data.setData(vos);
            data.setTotal(total);
            return ResultBean.successfulResult(data);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }


    }


    /**
     * 余额动账明细
     *
     * @param accessToken
     * @param pageNumber
     * @param pageSize
     * @param remId
     * @return
     */
    public ResultBean<ApiData<HouseRemainingRecordVo>> listRemainingRecord(String accessToken, Integer pageNumber, Integer pageSize, Long remId) {
        try {
            ApiData<HouseRemainingRecordVo> apiData = new ApiData<>();
            List<HouseRemainingRecordVo> data = new ArrayList<>();

            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }

            Page<HouseRemainingRecord> records = houseRemainingRecordRepository.findByRemainingIdAndStatus(remId, 1, PageRequest.of(pageNumber, pageSize));
            List<HouseRemainingRecord> total = houseRemainingRecordRepository.findByRemainingIdAndStatus(remId, 1);
            data = ObjectConversion.copy(records.getContent(), HouseRemainingRecordVo.class);
            data.forEach(m -> m.setOperateMoney(ConvertUtils.fenToYuan(m.getOperateMoney())));
            apiData.setData(data);
            apiData.setTotal((long) total.size());
            return ResultBean.successfulResult(apiData);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }


    }

    /**
     * 账户管理-单位账户列表
     */
    public ResultBean<ApiData<DepRemainingVo>> depRemainingList(String accessToken, String depName, Integer pageNumber, Integer pageSize) {
        try {
            ApiData<DepRemainingVo> apiData = new ApiData<>();
            List<DepRemainingVo> data = new ArrayList<>();

            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }

            Long orgId = token.getEnterpriseId();
            String userId = token.getId();


            // 判断用户所属机构是否设置层级架构
            DepartmentHierarchy hierarchy = departmentHierarchyRepository.findByOrgIdAndStatus(orgId, 1);
            if (hierarchy == null) {
                return ResultBean.failedResultWithMsg("用户所属机构未设置层级架构");
            }
            // 查询出企业的标签
            Long id = hierarchy.getId();
            List<DepartmentEnterpriseTagRef> refs = departmentEnterpriseTagRefRepository.findByDepRefId(id);
            List<Long> enterpriseTagIds = refs.stream().map(DepartmentEnterpriseTagRef::getTagId).distinct().collect(Collectors.toList());// 用户企业标签


            String depSql = "SELECT\n" +
                    "\tdr.id AS depRemainingId,\n" +
                    "\tdr.dep_id AS depId,\n" +
                    "\tdr.dep_name AS depName,\n" +
                    "\tdr.house_id AS houseId,\n" +
                    "\tdr.org_id AS orgId,\n" +
                    "\tdr.balance_fee AS balanceFee,\n" +
                    "\tdr.cash_pledge AS cashPledge,\n" +
                    "\tdr.last_update_time AS lastUpdateTime,\n" +
                    "\tdr.create_time AS createTime,\n" +
                    "\tdr.`status` AS status, \n" +
                    "\td.`name` AS orgName \n" +
                    "FROM\n" +
                    "saas_department_remaining dr " +
                    "LEFT JOIN saas_department d ON d.id = dr.org_id \n";

            List<Object> args = new ArrayList<>();
            StringBuilder where = new StringBuilder(" WHERE 1 = 1 and dr.status = 1 ");

            String offsets = "   LIMIT ? OFFSET ? ";
            // 单位承租人
            if (enterpriseTagIds.contains(7L)) {
                where.append(" and dr.dep_id = ? ");
            } else {
                // 非单位承租人
                where.append(" and dr.org_id = ? ");
            }
            args.add(orgId);

            if (StringUtils.isNotBlank(depName)) {
                where.append("  AND  dr.dep_name  like ?   \n");
                args.add("%" + depName + "%");
            }


            // 统计总数
            String count = "select count(1) FROM (" + depSql + where + ") c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, args.toArray());
            if (total == 0) {
                apiData.setTotal(total);
                apiData.setData(data);
                return ResultBean.successfulResult(apiData);
            }


            where.append("  ORDER BY ").append(" dr.create_time desc ").append(" \n").append(offsets);
            args.add(pageSize);
            args.add(pageNumber * pageSize);

            data = jdbcTemplate.query(depSql + where, new BeanPropertyRowMapper<>(DepRemainingVo.class), args.toArray());

            data.forEach(m -> {
                m.setBalanceFee(ConvertUtils.fenToYuan(m.getBalanceFee()));
                m.setCashPledge(ConvertUtils.fenToYuan(m.getCashPledge()));
            });

            apiData.setData(data);
            apiData.setTotal(total);

            return ResultBean.successfulResult(apiData);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 账户管理-单位账户详情列表
     *
     * @param accessToken
     * @param communityId
     * @param buildingNum
     * @param unit
     * @param roomNumber
     * @param pageNumber
     * @param pageSize
     * @param depRemainingId
     * @return
     */
    public ResultBean<ApiData<DepRemainingHouseVo>> depRemainingHouseList(String accessToken, String communityId, Long buildingNum,
                                                                          Long unit, String roomNumber, Integer pageNumber, Integer pageSize, Long depRemainingId) {


        try {
            ApiData<DepRemainingHouseVo> apiData = new ApiData<>();
            List<DepRemainingHouseVo> data = new ArrayList<>();


            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }

            if (depRemainingId == null) {
                return ResultBean.failedResultOfParamWithMsg("参数有误");
            }

            String depSql = "SELECT\n" +
                    "\tdr.id AS depRemainingId,\n" +
                    "\tdr.dep_id AS depId,\n" +
                    "\tdr.dep_name AS depName,\n" +
                    "\tdr.house_id AS houseId,\n" +
                    "\tdr.org_id AS orgId,\n" +
                    "\tdrr.create_time AS createTime,\n" +
                    "\tdrr.id AS depRemainingRefId,\n" +
                    "\tdrr.rent_withhold_status AS rentWithholdStatus,\n" +
                    "\tdrr.else_withhold_status AS elseWithholdStatus,\n" +
                    "\tdr.`status` AS status,\n" +
                    "\tsc.id AS communityId,\n" +
                    "\tsc.`name` AS communityName,\n" +
                    "\tscb.id AS buildingNum,\n" +
                    "\tscb.`name` AS buildingNumName,\n" +
                    "\tscbu.id AS unit,\n" +
                    "\tscbu.`name` AS unitName,\n" +
                    "\th.room_number AS roomNumber\n" +
                    "FROM\n" +
                    "\tsaas_department_remaining_ref drr\n" +
                    "\tLEFT JOIN saas_department_remaining dr ON drr.remaining_id = dr.id\n" +
                    "\tLEFT JOIN saas_house h ON drr.house_id = h.id\n" +
                    "\tLEFT JOIN saas_community sc ON h.residence_community_id = sc.id\n" +
                    "\tLEFT JOIN saas_community_build scb ON h.building_num = scb.id\n" +
                    "\tLEFT JOIN saas_community_build_unit scbu ON h.unit = scbu.id ";


            List<Object> args = new ArrayList<>();
            StringBuilder where = new StringBuilder(" WHERE 1 = 1 ");
            where.append(" and  drr.remaining_id = ? ");
            args.add(depRemainingId);

            // 条件查询
            if (!StringUtils.isEmpty(communityId)) {
                where.append(" and  h.residence_community_id = ? ");
                args.add(communityId);
            }
            if (!StringUtils.isEmpty(roomNumber)) {
                where.append(" and  h.room_number = ? ");
                args.add(roomNumber);
            }

            if (buildingNum != null) {
                where.append(" and h.building_num = ? ");
                args.add(buildingNum);
            }

            if (unit != null) {
                where.append(" and h.unit = ? ");
                args.add(unit);
            }

            // 查询总记录数
            String count = "select count(1) FROM (" + depSql + where + ") c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, args.toArray());
            if (total == 0) {
                apiData.setData(data);
                apiData.setTotal(total);
                return ResultBean.successfulResult(apiData);
            }

            args.add(pageSize);
            args.add(pageNumber * pageSize);

            data = jdbcTemplate.query(depSql + where + SQL_PAGE, new BeanPropertyRowMapper<>(DepRemainingHouseVo.class), args.toArray());
            for (DepRemainingHouseVo datum : data) {
                Long remId = datum.getDepRemainingId();
                String houseId = datum.getHouseId();
                List<DepartmentRemainingRecord> records = departmentRemainingRecordRepository.findByRemainingIdAndHouseId(remId, houseId);
                int totalCost = 0;
                if (!records.isEmpty()) {
                    totalCost = records.stream().mapToInt(DepartmentRemainingRecord::getOperateMoney).sum();
                }
                datum.setTotalCost(ConvertUtils.fenConvertYuan(totalCost));
            }


            apiData.setData(data);
            apiData.setTotal(total);
            return ResultBean.successfulResult(apiData);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }


    /**
     * 账户管理-单位房产账单代扣更改
     *
     * @return
     */
    public ResultBean<Object> depRemainingUpdateStatus(String accessToken, DepRemainingHouseVo vo) {
        try {
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }
            Long refId = vo.getDepRemainingRefId();
            if (refId == null) {
                return ResultBean.failedResultOfParamWithMsg("房屋详情信息有误");
            }
            Optional<DepartmentRemainingRef> byId = departmentRemainingRefRepository.findById(refId);
            if (!byId.isPresent()) {
                return ResultBean.failedResultWithMsg("未找到该单位账户关联房屋信息");
            }
            DepartmentRemainingRef ref = byId.get();
            ref.setElseWithholdStatus(vo.getElseWithholdStatus());
            ref.setRentWithholdStatus(vo.getRentWithholdStatus());
            departmentRemainingRefRepository.save(ref);

            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 账户管理-单位房产账单代扣明细
     */
    public ResultBean<ApiData<BillListVo>> depRemainingHouseBill(String accessToken, Long refId) {
        try {
            ApiData<BillListVo> apiData = new ApiData<>();
            List<BillListVo> data = new ArrayList<>();

            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }
            if (refId == null) {
                return ResultBean.failedResultOfParamWithMsg("房屋详情信息有误");
            }

            Optional<DepartmentRemainingRef> byId = departmentRemainingRefRepository.findById(refId);
            if (!byId.isPresent()) {
                return ResultBean.failedResultWithMsg("未找到该单位账户关联房屋信息");
            }
            DepartmentRemainingRef ref = byId.get();
            String houseId = ref.getHouseId();
            Long remainingId = ref.getRemainingId();

            // 余额扣款记录
            List<DepartmentRemainingRecord> remainingRecord = departmentRemainingRecordRepository.findByRemainingIdAndHouseId(remainingId, houseId);
            if (!remainingRecord.isEmpty()) {
                for (DepartmentRemainingRecord record : remainingRecord) {
                    // 账单类型
                    Integer billStatus = record.getBillStatus();
                    BillListVo billListVo = new BillListVo();

                    // 其他账单
                    if (billStatus != 9 && billStatus != 8) {
                        Long billId = record.getBillId();
                        Optional<EstateExpenseBill> byId1 = estateExpenseBillRepository.findById(billId);
                        if (!byId1.isPresent()) {
                            log.warn("当前账单不存在： " + billId);
                            continue;
                        }
                        EstateExpenseBill bill = byId1.get();
                        billListVo.setStartTime(bill.getStartTime());
                        billListVo.setEndTime(bill.getEndTime());
                        billListVo.setExpense(ConvertUtils.fenConvertYuan(bill.getCost()));
                        billListVo.setId(billId);
                        billListVo.setChargeType(billStatus);
                        billListVo.setCreateTime(bill.getCreateTime());
                        billListVo.setPaymentTime(bill.getPaymentTime());
                        billListVo.setPaymentStatus(bill.getPaymentStatus());
                        data.add(billListVo);
                    } else {
                        // 租金押金
                        Long billId = record.getBillId();
                        Optional<EstateRentBill> byId1 = estateRentBillRepository.findById(billId);
                        if (!byId1.isPresent()) {
                            log.warn("当前账单不存在： " + billId);
                            continue;
                        }
                        EstateRentBill bill = byId1.get();
                        billListVo.setStartTime(bill.getStartTime());
                        billListVo.setEndTime(bill.getEndTime());
                        billListVo.setExpense(ConvertUtils.fenConvertYuan(bill.getCost()));
                        billListVo.setId(billId);
                        billListVo.setChargeType(billStatus);
                        billListVo.setCreateTime(bill.getCreateTime());
                        billListVo.setPaymentTime(bill.getPaymentTime());
                        billListVo.setPaymentStatus(bill.getPaymentStatus());
                        data.add(billListVo);
                    }
                }
            }
            apiData.setData(data);
            apiData.setTotal((long) data.size());
            return ResultBean.successfulResult(apiData);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 账户管理-个人承租人/单位承租人 缴费记录明细
     *
     * @param accessToken
     * @param pageNumber
     * @param pageSize
     * @param houseId     房产id
     * @param accountType 账户类型 0个人承租人  1单位承租人
     * @return
     */
    public ResultBean<PaymentOrderApiData<PaymentRecordVo>> paymentRecords(String accessToken, Integer pageNumber, Integer pageSize, String houseId, Long id, Integer accountType, String communityId, Long buildingNum,
                                                                           Long unit, String roomNumber, String name) {
        try {
            PaymentOrderApiData<PaymentRecordVo> apiData = new PaymentOrderApiData<>();

            List<PaymentRecordVo> vos = new ArrayList<>();
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }

            Long orgId = token.getEnterpriseId();
            if (accountType == null) {
                return ResultBean.failedResultOfParamWithMsg("参数有误");
            }
            String remSql = "SELECT\n" +
                    "\trr.operate_money AS cost,\n" +
                    "\trr.last_update_time AS paymentTime,\n" +
                    "IF\n" +
                    "\t( rr.bill_status = 5, 1, 0 ) AS paymentType,\n" +
                    "\tsc.id AS communityId,\n" +
                    "\tr.house_id AS houseId,\n" +
                    "\tsc.`name` AS communityName,\n" +
                    "\tscb.id AS buildingNum,\n" +
                    "\tscb.`name` AS buildingNumName,\n" +
                    "\tscbu.id AS unit,\n" +
                    "\tscbu.`name` AS unitName,\n" +
                    "\th.room_number AS roomNumber,\n" +
                    "\tchu.`name` AS matchUserName,\n" +
                    "\tr.match_user_id AS matchUserId \n" +
                    "FROM\n" +
                    "\t`saas_house_remaining_record` rr\n" +
                    "\tLEFT JOIN saas_house_remaining r ON rr.remaining_id = r.id\n" +
                    "\tLEFT JOIN saas_house h ON r.house_id = h.id\n" +
                    "\tLEFT JOIN saas_community sc ON h.residence_community_id = sc.id\n" +
                    "\tLEFT JOIN saas_community_build scb ON h.building_num = scb.id\n" +
                    "\tLEFT JOIN saas_community_build_unit scbu ON h.unit = scbu.id\n" +
                    "\tLEFT JOIN saas_community_house_user chu ON r.house_id = chu.community_house_id \n" +
                    "\tAND chu.type = 1  and chu.status = 1  and rr.operate_status != 3 ";

            List<Object> args = new ArrayList<>();
            StringBuilder where = new StringBuilder(" WHERE 1 = 1 \n");

            if (orgId != null) {
                where.append("  AND  r.org_id = ?  \n");
                args.add(orgId);
            }
            if (!StringUtils.isEmpty(houseId)) {
                where.append("  AND  r.house_id = ?  \n");
                args.add(houseId);
            }

            if (!StringUtils.isEmpty(communityId)) {
                where.append(" and  h.residence_community_id = ? ");
                args.add(communityId);
            }
            if (!StringUtils.isEmpty(roomNumber)) {
                where.append(" and  h.room_number = ? ");
                args.add(roomNumber);
            }

            if (buildingNum != null) {
                where.append(" and h.building_num = ? ");
                args.add(buildingNum);
            }

            if (unit != null) {
                where.append(" and h.unit = ? ");
                args.add(unit);
            }

            if (!StringUtils.isEmpty(name)) {
                where.append(" and  chu.name  like '%").append(name).append("%' ");
            }

            if (null != accountType) {
                if (accountType == 0) {
                    where.append("  AND  r.type = 1  \n");
                } else {
                    where.append("  AND  r.type = 2  \n");
                }
            }

            where.append(" AND rr.operate_status = 1 AND rr.update_status = 1 AND rr.status = 1  ");


            // 统计总数
            String count = "select count(1) FROM (" + remSql + where + ") c  ";
            String countCost = "select SUM(c.cost) FROM (" + remSql + where + ") c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, args.toArray());
            Long totalCost = jdbcTemplate.queryForObject(countCost, Long.class, args.toArray());
            if (total == 0) {
                apiData.setData(vos);
                apiData.setTotal(total);
                apiData.setTotalAmount(ConvertUtils.fenConvertYuan(totalCost));
                return ResultBean.successfulResult(apiData);
            }

            String offsets = "  LIMIT ? OFFSET ? ";
            // 查询分页数据
            where.append("  ORDER BY ").append(" rr.last_update_time DESC ").append(" \n").append(offsets);
            args.add(pageSize);
            args.add(pageNumber * pageSize);

            vos = jdbcTemplate.query(remSql + where, new BeanPropertyRowMapper<>(PaymentRecordVo.class), args.toArray());
            vos.forEach(m -> {
                m.setCost(ConvertUtils.fenToYuan(m.getCost()));
                // 单位承租人
                if (!StringUtils.isEmpty(m.getMatchUserId()) && StringUtils.isEmpty(m.getMatchUserName())) {
                    List<MatchUser> matchUserList = matchUserRepository.findByUserId(m.getMatchUserId());
                    if (CollectionUtil.isNotEmpty(matchUserList)) {
                        MatchUser matchUser = matchUserList.get(0);
                        m.setMatchUserName(matchUser.getName());
                    }
                }


            });

            apiData.setData(vos);
            apiData.setTotal(total);
            apiData.setTotalAmount(ConvertUtils.fenConvertYuan(totalCost));
            return ResultBean.successfulResult(apiData);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }


    /**
     * 数据记录-延期记录
     *
     * @param accessToken
     * @param residenceCommunityId 小区
     * @param buildingNum          楼栋
     * @param unit                 单元
     * @param roomNumber           房号
     * @param name                 承租人
     * @param pageNumber
     * @param pageSize
     * @param postponeType         延期状态  0延期 1取消延期
     * @return
     */
    public ResultBean<ApiData<PostponeVo>> postponeList(String accessToken, String residenceCommunityId, Long buildingNum,
                                                        Long unit, String roomNumber, String houseId, String name, Integer pageNumber, Integer pageSize, Integer postponeType) {
        try {
            ApiData<PostponeVo> apiData = new ApiData<>();
            List<PostponeVo> data = new ArrayList<>();
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }

            Long orgId = token.getEnterpriseId();
            String postponeSql = "SELECT\n" +
                    "\t rp.remaining_id AS remainingId," +
                    "rp.id as  postponeId ," +
                    "r.house_id as houseId ,\n" +
                    "\t sc.id AS communityId,\n" +
                    "\t sc.`name` AS communityName,\n" +
                    "\t scb.id AS buildingNum,\n" +
                    "\t scb.`name` AS buildingNumName,\n" +
                    "\t scbu.id AS unit,\n" +
                    "\t scbu.`name` AS unitName,\n" +
                    "\t h.room_number AS roomNumber,\n" +
                    "\t chu.`name` AS matchUserName,\n" +
                    "\t chu.user_id AS matchUserId,\n" +
                    "\t rp.postpone_type as postponeType,\n" +
                    "\t rp.operator_id as operatorId,\n" +
                    "\t rp.last_update_time as lastUpdateTime,\n" +
                    "\t rp.cause as cause,\n" +
                    "\t rp.deferred_start_time as deferredStartTime,\n" +
                    "\t rp.deferred_end_time as deferredEndTime," +
                    "\t rp.cancel_status as cancelStatus, \n" +
                    "\t rp.postpone_id as remPostponeId \n" +
                    "\t FROM\n" +
                    "\t saas_house_remaining_postpone rp \n" +
                    "\t LEFT JOIN saas_house_remaining r ON rp.remaining_id = r.id\n" +
                    "\t LEFT JOIN saas_house h ON r.house_id = h.id\n" +
                    "\t LEFT JOIN saas_community sc ON h.residence_community_id = sc.id\n" +
                    "\t LEFT JOIN saas_community_build scb ON h.building_num = scb.id\n" +
                    "\t LEFT JOIN saas_community_build_unit scbu ON h.unit = scbu.id\n" +
                    "\t LEFT JOIN saas_community_house_user chu ON r.house_id = chu.community_house_id and chu.type = 1 and chu.status = 1 \n" +
                    "\tWHERE\n" +
                    "\t1 = 1 ";


            StringBuilder where = new StringBuilder();
            List<Object> age = new ArrayList<>();

            // 登录类型
            Integer loginType = token.getLoginType();
            String userId = token.getId();

            // 用户对应房屋
            List<Map<String, Object>> communityList = appCommunityService.findCommunity(accessToken).getResultData();

            if (loginType == 1) {// 企业用户
                // 企业用户拼接小区id
                if (communityList != null && !communityList.isEmpty()) {
                    StringBuilder communityIds = new StringBuilder("");
                    for (Map<String, Object> map : communityList) {
                        communityIds.append("'" + map.get("communityId") + "'").append(",");
                    }
                    String communityIdsStr = communityIds.toString().substring(0, communityIds.toString().lastIndexOf(","));

                    postponeSql += "  AND h.residence_community_id IN (  " + communityIdsStr + " )  ";
                } else {
                    postponeSql += "  AND h.residence_community_id IN ( null )  ";
                }
            } else {// 非企业用户
                // 登录用户名下房屋
                List<String> houseIdList = communityService.getHouseIdList(userId);
                if (houseIdList.isEmpty()) {
                    return ResultBean.successfulResult(apiData);
                }

                // 查名下管理房屋的成员
                StringBuilder houseIds = new StringBuilder("");
                for (String hId : houseIdList) {
                    houseIds.append("'" + hId + "'").append(",");
                }
                String houseIdsStr = houseIds.toString().substring(0, houseIds.toString().lastIndexOf(","));
                postponeSql += "  and h.residence_community_id IN (  " + houseIdsStr + " )  ";
            }
            // 条件查询
            if (!StringUtils.isEmpty(residenceCommunityId)) {
                where.append(" and  h.residence_community_id = ? ");
                age.add(residenceCommunityId);
            }
            if (!StringUtils.isEmpty(roomNumber)) {
                where.append(" and  h.room_number = ? ");
                age.add(roomNumber);
            }
            if (!StringUtils.isEmpty(houseId)) {
                where.append(" and  h.id = ? ");
                age.add(houseId);
            }

            if (buildingNum != null) {
                where.append(" and h.building_num = ? ");
                age.add(buildingNum);
            }

            if (unit != null) {
                where.append(" and h.unit = ? ");
                age.add(unit);
            }

            if (!StringUtils.isEmpty(name)) {
                where.append(" and  chu.name  like '%" + name + "%' ");
            }

            if (postponeType != null) {
                where.append(" and  rp.postpone_type  = ? ");
                age.add(postponeType);
                if (postponeType == 0) {
                    where.append(" and  rp.cancel_status  = 0 ");
                }
            }

            if (orgId != null) {
                where.append(" and  r.org_id  = ? ");
                age.add(orgId);
            }
            // 查询总记录数
            String count = "select count(1) FROM (" + postponeSql + where + ") c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, age.toArray());
            if (total == 0) {
                apiData.setData(data);
                apiData.setTotal(total);
                return ResultBean.successfulResult(apiData);
            }

            age.add(pageSize);
            age.add(pageNumber * pageSize);

            where.append(" ORDER BY  rp.last_update_time  desc ");

            data = jdbcTemplate.query(postponeSql + where + SQL_PAGE, new BeanPropertyRowMapper<>(PostponeVo.class), age.toArray());


            // 查询承租人名称
            // List<String> ids = data.stream().filter(vo -> vo.getMatchUserId() != null)
            //         .map(PostponeVo::getMatchUserId).distinct().collect(Collectors.toList());
            // if (!ids.isEmpty()) {
            //     List<AppUser> appUsers = appUserRepository.findByIdOrEnterpriseIn(ids, ids);
            //     for (AppUser appUser : appUsers) {
            //         for (PostponeVo vo : data) {
            //             if (null != vo.getMatchUserId() && vo.getMatchUserName() == null) {
            //                 if (vo.getMatchUserId().equals(appUser.getId())) {
            //                     vo.setMatchUserName(appUser.getName());
            //                 }
            //             }
            //         }
            //     }
            // }


            for (PostponeVo datum : data) {
                if (datum.getMatchUserName() == null) {
                    List<MatchUser> matchUserList = matchUserRepository.findByUserId(datum.getMatchUserId());
                    if (CollectionUtil.isNotEmpty(matchUserList)) {
                        MatchUser matchUser = matchUserList.get(0);
                        datum.setMatchUserName(matchUser.getName());
                    }
                    // List<MatchUserHouse> byHouseId = matchUserHouseRepository.findByHouseId(datum.getHouseId());
                    // if (!byHouseId.isEmpty()) {
                    //     MatchUserHouse matchUserHouse = byHouseId.get(0);
                    //     Optional<MatchUser> matchUserRepositoryById = matchUserRepository.findById(Long.parseLong(matchUserHouse.getMatchUserStockId()));
                    //     matchUserRepositoryById.ifPresent(matchUser -> datum.setMatchUserName(matchUser.getName()));
                    // }
                }
            }


            // 查询操作人名称
            List<String> operatorIds = data.stream().map(PostponeVo::getOperatorId)
                    .filter(Objects::nonNull).distinct().collect(Collectors.toList());
            if (!operatorIds.isEmpty()) {
                List<User> userS = userRepository.findByIdIn(operatorIds);
                for (User user : userS) {
                    for (PostponeVo vo : data) {
                        if (vo.getOperatorId() == null) {
                            vo.setOperatorName("系统管理员");
                        } else {
                            if (vo.getOperatorId().equals(user.getId())) {
                                vo.setOperatorName(user.getName());
                            }
                        }
                    }
                }
            }
            apiData.setData(data);
            apiData.setTotal(total);

            return ResultBean.successfulResult(apiData);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }


    /**
     * 审核人设置-审核人列表
     *
     * @param accessToken
     * @param orgId
     * @param type
     * @return
     */
    public ResultBean<ApiData<AuditorVo>> auditorList(String accessToken, Long orgId, Integer type) {
        log.info("AccountManageService auditorList orgId={},type={}", orgId, type);
        try {
            ApiData<AuditorVo> apiData = new ApiData<>();
            List<AuditorVo> data = new ArrayList<>();

            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }

            if (orgId == null) {
                return ResultBean.failedResultOfParamWithMsg("机构参数有误");
            }
            String sql = "SELECT \n" +
                    "da.id,\n" +
                    "da.dep_id as depId,\n" +
                    "da.type,\n" +
                    "da.user_id as userId,\n" +
                    "u.name as userName,\n" +
                    "da.create_time as createTime,\n" +
                    "da.create_user_id as createUserId,\n" +
                    "u1.name as createUserName,\n" +
                    "da.`status`,\n" +
                    "u.mobile as phone ,\n" +
                    "da.last_update_time as lastUpdateTime,\n" +
                    "da.operator_id as operatorId,\n" +
                    "u2.name as operatorName\n" +
                    "FROM `saas_department_auditor` da \n" +
                    "LEFT JOIN saas_user u ON da.user_id = u.id\n" +
                    "LEFT JOIN saas_user u1 ON da.create_user_id = u1.id\n" +
                    "LEFT JOIN saas_user u2 ON da.operator_id = u2.id where 1 = 1 \n ";


            StringBuilder where = new StringBuilder();
            List<Object> age = new ArrayList<>();

            if (orgId != null) {
                where.append(" and  da.dep_id = ? ");
                age.add(orgId);
            }

            if (type != null) {
                where.append(" and  da.type = ? ");
                age.add(type);
            }

            // 查询总记录数
            String count = "select count(1) FROM (" + sql + where + ") c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, age.toArray());
            if (total == 0) {
                apiData.setData(data);
                apiData.setTotal(total);
                return ResultBean.successfulResult(apiData);
            }


            data = jdbcTemplate.query(sql + where, new BeanPropertyRowMapper<>(AuditorVo.class), age.toArray());

            apiData.setData(data);
            apiData.setTotal(total);
            return ResultBean.successfulResult(apiData);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 审核人设置-审核人 新增
     *
     * @param accessToken
     * @param vo
     * @return
     */
    @Transactional
    public ResultBean<ApiData<AuditorVo>> addAuditor(String accessToken, AuditorApi vo) {
        log.info("AccountManageService addAuditor vo={}", vo);
        try {
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }

            String userId = token.getId();
            Date date = new Date();
            Long orgId = vo.getOrgId();
            Integer type = vo.getType();
            if (orgId == null || type == null) {
                return ResultBean.failedResultOfParamWithMsg("参数有误");
            }
            List<AuditorVo> data = vo.getData();
            List<DepartmentAuditor> departmentAuditors = new ArrayList<>();
            // 机构对应审核人
            List<DepartmentAuditor> depIdAndType = departmentAuditorRepository.findByDepIdAndType(orgId, type);
            // 不可重复添加
            if (!depIdAndType.isEmpty()) {
                List<String> userIds = depIdAndType.stream().map(DepartmentAuditor::getUserId).collect(Collectors.toList());
                for (AuditorVo datum : data) {
                    if (userIds.contains(datum.getUserId())) {
                        return ResultBean.failedResultOfParamWithMsg("用户已授权，请勿重复授权");
                    }
                    DepartmentAuditor auditor = new DepartmentAuditor();
                    BeanUtils.copyProperties(auditor, datum);
                    auditor.setCreateUserId(userId);
                    auditor.setCreateTime(date);
                    // 0禁用 1启用 2已删除
                    auditor.setStatus(1);
                    departmentAuditors.add(auditor);
                }

            } else {
                for (AuditorVo datum : data) {
                    DepartmentAuditor auditor = new DepartmentAuditor();
                    BeanUtils.copyProperties(auditor, datum);
                    auditor.setCreateUserId(userId);
                    auditor.setCreateTime(date);
                    // 0禁用 1启用 2已删除
                    auditor.setStatus(1);
                    departmentAuditors.add(auditor);
                }
            }
            departmentAuditorRepository.saveAll(departmentAuditors);

            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }


    /**
     * 校验审核权限
     *
     * @param token
     * @param type  0账单审核  1缴费凭证审核
     * @return
     */
    public Boolean checkAuditor(String token, Integer type) {

        Boolean flag = false;
        if (type == null) {
            return flag;
        }

        TokenRedisVo tokenVo = redisService.findTokenVo(token);
        if (token == null) {
            return flag;
        }

        // 获取depId
        String userId = tokenVo.getId();
        Long depId = tokenVo.getEnterpriseId();
        if (depId == null) {
            User user = userRepository.findById(tokenVo.getId());
            if (user != null) {
                UserDepartmentRef depRef = userDepartmentRefRepository.findByUserId(user.getId()).get(0);
                depId = depRef.getDepId();
            }
        }

        // 判断是否设置审核人
        List<DepartmentAuditor> depList = departmentAuditorRepository.findByDepIdAndType(depId, type);
        if (!depList.isEmpty()) {
            List<String> userIds = depList.stream().map(DepartmentAuditor::getUserId).distinct().collect(Collectors.toList());
            if (userIds.contains(userId)) {
                flag = true;
            }
        }
        return flag;
    }

    /**
     * 删除审核人
     *
     * @param accessToken
     * @param vo
     * @return
     */
    public ResultBean<Object> deleteAuditor(String accessToken, AuditorApi vo) {
        try {
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }

            List<AuditorVo> data = vo.getData();
            if (data.isEmpty()) {
                return ResultBean.failedResultOfParamWithMsg("参数有误");
            }

            List<Long> auditorIds = data.stream().map(AuditorVo::getId).collect(Collectors.toList());
            departmentAuditorRepository.deleteByIdIn(auditorIds);

            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 账单列表-违约金列表
     *
     * @param accessToken
     * @param pageNumber
     * @param pageSize
     * @param filter
     * @return
     */
    public ResultBean<ApiData<PenalSumVO>> penalSumList(String accessToken, Integer pageNumber, Integer pageSize, BillSearchRequestVO filter) {
        try {
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }
            ApiData<PenalSumVO> data = new ApiData<>();
            List<PenalSumVO> list = new ArrayList<>();


            // 租金
            String rentSql = "SELECT\n" +
                    "\tb.`id`  as billId,\n" +
                    "\tb.`house_id` AS houseId,\n" +
                    "\tb.`room_number` AS roomNumber,\n" +
                    "\tb.`org_id` AS orgId,\n" +
                    "\tb.`match_user_id` AS matchUserId,\n" +
                    "\tvb.`bill_type` AS chargeType,\n" +
                    "\tb.`measure_unit` AS measureUnit,\n" +
                    "\tb.`cost` as billCost,\n" +
                    "\tb.`start_time` AS startTime,\n" +
                    "\tb.`end_time` AS endTime,\n" +
                    "\tb.`create_time` AS createTime,\n" +
                    "\tb.should_pay_time AS shouldPayTime,\n" +
                    "\tb.surplus_cost AS billSurplusCost,\n" +
                    "\t2 AS houseType,\n" +
                    "\tIFNULL( u.NAME, ui.NAME ) AS matchUserName,\n" +
                    "\tIFNULL( u.mobile, ui.phone ) AS phone,\n" +
                    "\tbr.collection_org AS collectionOrg,\n" +
                    "\tvb.growth_cost as growthCost,\n" +
                    "\tvb.cost as penalSumCost,\n" +
                    "\tvb.create_time as penalSumTime,\n" +
                    "\tvb.payment_time as paymentTime,\n" +
                    "\tvb.status as violateBillStatus,\n" +
                    "\tvb.payment_status as paymentStatus,vb.operator_id as operatorId,\n" +
                    "\tvb.operator_time as operatorTime ,br.violate_status as violateStatus , br.violate_ratio as violateRatio," +
                    "\tsc.id AS communityId,\n" +
                    "\tsc.`name` AS communityName,\n" +
                    "\tscb.id AS buildingNum,\n" +
                    "\tscb.`name` AS buildingNumName,\n" +
                    "\tscbu.id AS unit,\n" +
                    "\tscbu.`name` AS unitName ,vb.id as violateId \n" +
                    "FROM\n" +
                    "  (SELECT * FROM saas_estate_violate_bill WHERE bill_type in (8,9) ) as  vb\n" +
                    "\tLEFT JOIN `saas_estate_rent_bill` b ON vb.bill_id = b.id\n" +
                    "\tLEFT JOIN `saas_community_house_user` u ON u.`community_house_id` = b.house_id \n" +
                    "\tAND u.STATUS = 1 \n" +
                    "\tAND u.type = 1\n" +
                    "\tLEFT JOIN (\n" +
                    "\tSELECT\n" +
                    "\t\ta.house_id,\n" +
                    "\t\tb.NAME,\n" +
                    "\t\tc.phone \n" +
                    "\tFROM\n" +
                    "\t\tsaas_house_match_user a\n" +
                    "\t\tLEFT JOIN saas_house_eligible_apply b ON b.id = a.apply_id\n" +
                    "\t\tLEFT JOIN saas_app_user c ON c.id = a.match_user_id \n" +
                    "\tWHERE\n" +
                    "\t\ta.STATUS = 1 \n" +
                    "\t) ui ON ui.`house_id` = b.house_id\n" +
                    "\tLEFT JOIN saas_house_expense_bill_rule br ON b.rule_id = br.id\n" +
                    "\tLEFT JOIN saas_house h ON b.house_id = h.id\n" +
                    "\tLEFT JOIN saas_community sc ON h.residence_community_id = sc.id\n" +
                    "\tLEFT JOIN saas_community_build scb ON h.building_num = scb.id\n" +
                    "\tLEFT JOIN saas_community_build_unit scbu ON h.unit = scbu.id" +
                    "";
            // 账单
            String billSql = "SELECT\n" +
                    "\tb.`id`  as billId,\n" +
                    "\tb.`house_id` AS houseId,\n" +
                    "\tb.`room_number` AS roomNumber,\n" +
                    "\tb.`org_id` AS orgId,\n" +
                    "\tb.`match_user_id` AS matchUserId,\n" +
                    "\tvb.`bill_type`  AS chargeType,\n" +
                    "\tb.`measure_unit` AS measureUnit,\n" +
                    "\tb.`cost` as billCost,\n" +
                    "\tb.`start_time` AS startTime,\n" +
                    "\tb.`end_time` AS endTime,\n" +
                    "\tb.`create_time` AS createTime,\n" +
                    "\tb.should_pay_time AS shouldPayTime,\n" +
                    "\tb.surplus_cost AS billSurplusCost,\n" +
                    "\t2 AS houseType,\n" +
                    "\tIFNULL( u.NAME, ui.NAME ) AS matchUserName,\n" +
                    "\tIFNULL( u.mobile, ui.phone ) AS phone,\n" +
                    "\tbr.collection_org AS collectionOrg,\n" +
                    "\tvb.growth_cost as growthCost,\n" +
                    "\tvb.cost as penalSumCost,\n" +
                    "\tvb.create_time as penalSumTime,\n" +
                    "\tvb.payment_time as paymentTime,\n" +
                    "\tvb.status as violateBillStatus,\n" +
                    "\tvb.payment_status as paymentStatus ,vb.operator_id as operatorId,\n" +
                    "\tvb.operator_time as operatorTime ,br.violate_status as violateStatus , br.violate_ratio as violateRatio, \n" +
                    "\tsc.id AS communityId,\n" +
                    "\tsc.`name` AS communityName,\n" +
                    "\tscb.id AS buildingNum,\n" +
                    "\tscb.`name` AS buildingNumName,\n" +
                    "\tscbu.id AS unit,\n" +
                    "\tscbu.`name` AS unitName ,vb.id as violateId \n" +
                    "FROM\n" +
                    "  (SELECT * FROM saas_estate_violate_bill WHERE bill_type in (1,2,3,4,5,6,7) ) as  vb\n" +
                    "\tLEFT JOIN `saas_estate_expense_bill` b ON vb.bill_id = b.id\n" +
                    "\tLEFT JOIN `saas_community_house_user` u ON u.`community_house_id` = b.house_id \n" +
                    "\tAND u.STATUS = 1 \n" +
                    "\tAND u.type = 1\n" +
                    "\tLEFT JOIN (\n" +
                    "\tSELECT\n" +
                    "\t\ta.house_id,\n" +
                    "\t\tb.NAME,\n" +
                    "\t\tc.phone \n" +
                    "\tFROM\n" +
                    "\t\tsaas_house_match_user a\n" +
                    "\t\tLEFT JOIN saas_house_eligible_apply b ON b.id = a.apply_id\n" +
                    "\t\tLEFT JOIN saas_app_user c ON c.id = a.match_user_id \n" +
                    "\tWHERE\n" +
                    "\t\ta.STATUS = 1 \n" +
                    "\t) ui ON ui.`house_id` = b.house_id\n" +
                    "\tLEFT JOIN saas_house_expense_bill_rule br ON b.rule_id = br.id\n" +
                    "\tLEFT JOIN saas_house h ON b.house_id = h.id\n" +
                    "\tLEFT JOIN saas_community sc ON h.residence_community_id = sc.id\n" +
                    "\tLEFT JOIN saas_community_build scb ON h.building_num = scb.id\n" +
                    "\tLEFT JOIN saas_community_build_unit scbu ON h.unit = scbu.id";

            billSql = " select v.* from ( " + rentSql + " UNION ALL " + billSql + " ) v";


            List<Object> args = new ArrayList<>();
            StringBuilder where = new StringBuilder(" WHERE 1 = 1 \n");

            // 权限过滤
            List<Map<String, Object>> communityList = appCommunityService.findCommunity(accessToken).getResultData();
            if (communityList != null && !communityList.isEmpty()) {
                where.append(" and v.communityId in " + SqlUtils.foreachIn(communityList.size()));
                List<String> communityIds = communityList.stream().map(map -> {
                    String communityId = map.get("communityId").toString();
                    return communityId;
                }).collect(Collectors.toList());
                args.addAll(communityIds);
            } else {
                where.append(" and v.communityId in (null) ");
            }


            String offsets = "   LIMIT ? OFFSET ? ";


            // 条件查询
            if (StringUtils.isNotBlank(filter.getHouseId())) {
                where.append("  AND  v.`houseId` = ?  \n");
                args.add(filter.getHouseId());
            }
            if (StringUtils.isNotBlank(filter.getCommunityId())) {
                where.append("  AND  v.`communityId` = ?  \n");
                args.add(filter.getCommunityId());
            }
            if (filter.getBuildingNum() != null) {
                where.append("  AND  v.`buildingNum` =  ?  \n");
                args.add(filter.getBuildingNum());
            }
            if (filter.getUnit() != null) {
                where.append("  AND  v.`unit` =  ?  \n");
                args.add(filter.getUnit());
            }
            if (StringUtils.isNotBlank(filter.getRoomNumber())) {
                where.append("  AND  v.`roomNumber` = ?  \n");
                args.add(filter.getRoomNumber());
            }
            if (filter.getOrgId() != null) {
                where.append("  AND  v.`orgId` =  ?  \n");
                args.add(filter.getOrgId());
            }

            if (StringUtils.isNotBlank(filter.getMatchUserName())) {
                where.append("  AND  v.`matchUserName` like ?   \n");
                args.add("%" + filter.getMatchUserName() + "%");
            }

            if (filter.getChargeType() != null) {
                where.append("  AND  v.`chargeType` =  ?  \n");
                args.add(filter.getChargeType());
            }

            if (filter.getPaymentStatus() != null) {
                where.append("  AND  v.`paymentStatus` =  ?  \n");
                args.add(filter.getPaymentStatus());
            }

            // 查询总记录数
            String count = "select count(1) FROM (" + billSql + where + ") c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, args.toArray());
            // log.info("SQL :" + billSql + where);
            if (total == 0) {
                data.setData(list);
                data.setTotal(total);
                return ResultBean.successfulResult(data);
            }

            where.append("  ORDER BY ").append(" v.penalSumTime DESC ").append(" \n").append(offsets);
            args.add(pageSize);
            args.add(pageNumber * pageSize);

            list = jdbcTemplate.query(billSql + where, new BeanPropertyRowMapper<>(PenalSumVO.class), args.toArray());

            // 参数拼接
            list.forEach(m -> {
                m.setBillCost(ConvertUtils.fenToYuan(m.getBillCost()));
                m.setBillSurplusCost(ConvertUtils.fenToYuan(m.getBillSurplusCost()));
                m.setPenalSumCost(ConvertUtils.fenToYuan(m.getPenalSumCost()));
                m.setGrowthCost(ConvertUtils.fenToYuan(m.getGrowthCost()));

                if (StringUtils.isBlank(m.getMatchUserName()) || StringUtils.isBlank(m.getPhone())) {


                    if (StringUtils.isNotBlank(m.getMatchUserId())) {
                        List<MatchUser> matchUserList = matchUserRepository.findByUserId(m.getMatchUserId());
                        if (CollectionUtil.isNotEmpty(matchUserList)) {
                            m.setMatchUserName(matchUserList.get(0).getName());
                            m.setPhone(matchUserList.get(0).getPhone());
                        }
                    }
                    // List<MatchUserHouse> byHouseId = matchUserHouseRepository.findByHouseId(m.getHouseId());
                    // if (!byHouseId.isEmpty()) {
                    //     MatchUserHouse matchUserHouse = byHouseId.get(0);
                    //     Integer label = matchUserHouse.getLabel();
                    //     if (label == 1) {
                    //         // 个人承租人
                    //         List<CommunityHouseUser> communityHouseUserList = communityHouseUserRepository.findByCommunityHouseIdAndStatusAndType(m.getHouseId(), 1, 1);
                    //         if (communityHouseUserList != null && communityHouseUserList.size() > 0) {
                    //             m.setMatchUserName(communityHouseUserList.get(0).getName());
                    //             m.setPhone(communityHouseUserList.get(0).getMobile());
                    //         }
                    //     } else {
                    //         Optional<MatchUser> matchUserRepositoryById = matchUserRepository.findById(Long.parseLong(matchUserHouse.getMatchUserStockId()));
                    //         if (matchUserRepositoryById.isPresent()) {
                    //             // 产权下的用户承租人id
                    //             MatchUser byMatchUserId = matchUserRepositoryById.get();
                    //             m.setPhone(byMatchUserId.getPhone());
                    //         }
                    //         m.setMatchUserName(matchUserHouse.getCompanyName());
                    //     }
                    // }
                }
                // 1水费 2电费 3物业费 4宽带费 5电视费 6煤气费 7暖气费)
                Integer chargeType = m.getChargeType();
                switch (chargeType) {
                    case 1:
                        m.setChargeTypeName("水费");
                        break;
                    case 2:
                        m.setChargeTypeName("电费");
                        break;
                    case 3:
                        m.setChargeTypeName("物业费");
                        break;
                    case 4:
                        m.setChargeTypeName("宽带费");
                        break;
                    case 5:
                        m.setChargeTypeName("电视费");
                        break;
                    case 6:
                        m.setChargeTypeName("煤气费");
                        break;
                    case 7:
                        m.setChargeTypeName("暖气费");
                        break;
                    case 8:
                        m.setChargeTypeName("租金");
                        break;
                    case 9:
                        m.setChargeTypeName("押金");
                        break;
                }

            });

            data.setData(list);
            data.setTotal(total);

            return ResultBean.successfulResult(data);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }

    }

    /**
     * 账单列表 - 违约金减免
     *
     * @param accessToken
     * @param violateId
     */
    public ResultBean<Object> penalSumMitigate(String accessToken, Long violateId) {
        log.info("AccountManageService penalSumMitigate violateId={}", violateId);
        try {
            // 校验登录信息
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }
            String userId = tokenRedisVo.getId();
            if (violateId == null) {
                return ResultBean.failedResultOfParamWithMsg("参数有误");
            }

            Optional<EstateViolateBill> byId = estateViolateBillRepository.findById(violateId);
            if (!byId.isPresent()) {
                return ResultBean.failedResultWithMsg("该账单不存在");
            }
            EstateViolateBill estateViolateBill = byId.get();
            // 0正常 1减免  2已删除
            estateViolateBill.setStatus(1);
            estateViolateBill.setOperatorId(userId);
            estateViolateBill.setOperatorTime(new Date());
            estateViolateBillRepository.save(estateViolateBill);

            // 待办事项更新
            propertyOtherItem(violateId);

            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }


    /**
     * 非公租房其他账单待办事项
     */
    public void propertyOtherItem(Long billId) {
        List<BacklogItemPropertyOtherBill> propertyOtherBill = backlogItemPropertyOtherBillRepository.findByBillId(billId);
        if (propertyOtherBill != null && propertyOtherBill.size() > 0) {
            Date date = new Date();
            for (BacklogItemPropertyOtherBill bill : propertyOtherBill) {
                Optional<BacklogItem> itemOpt = backlogItemRepository.findById(bill.getBacklogItemId());
                if (itemOpt.isPresent()) {
                    BacklogItem item = itemOpt.get();
                    item.setBusinessStatus("已缴费");
                    item.setHandleStatus(1);
                    item.setHandlerTime(date);
                    backlogItemRepository.save(item);
                }
            }
        }

    }

    /**
     * 退费记录
     *
     * @param accessToken
     * @param residenceCommunityId
     * @param buildingNum
     * @param unit
     * @param roomNumber
     * @param name
     * @param pageNumber
     * @param pageSize
     * @param paymentStatus
     * @return
     */
    public ResultBean<ApiData<RetiredVo>> returnList(String accessToken, String residenceCommunityId, Long buildingNum,
                                                     Long unit, String roomNumber, String name, Integer pageNumber, Integer pageSize, Integer paymentStatus, Integer type) {
        try {
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }

            ApiData<RetiredVo> apiData = new ApiData<>();
            List<RetiredVo> data = new ArrayList<>();


            String sql = "SELECT\n" +
                    "\thrm.id as returnId,\n" +
                    "\thrm.remaining_id AS remainingId,\n" +
                    "\tsc.id AS communityId,\n" +
                    "\tsc.`name` AS communityName,\n" +
                    "\tscb.id AS buildingNum,\n" +
                    "\tscb.`name` AS buildingNumName,\n" +
                    "\tscbu.id AS unit,\n" +
                    "\tscbu.`name` AS unitName,\n" +
                    "\th.room_number AS roomNumber,\n" +
                    "\thrm.match_user_name AS matchUserName,\n" +
                    "\thrm.match_user_id AS matchUserId,\n" +
                    "\thrm.cost as cost,\n" +
                    "\thrm.other_cost as otherCost,\n" +
                    "\thrm.type as returnType,\n" +
                    "\thrm.payment_status as paymentStatus,\n" +
                    "\thrm.payment_time as paymentTime,\n" +
                    "\thrm.create_id as createId,\n" +
                    "\tmuh.start_date AS startDate,\n" +
                    "\tmuh.end_date AS endDate     \n" +
                    "FROM\n" +
                    "\tsaas_house_return_premium hrm\n" +
                    "\tLEFT JOIN saas_house h ON hrm.house_id = h.id\n" +
                    "\tLEFT JOIN saas_community sc ON h.residence_community_id = sc.id\n" +
                    "\tLEFT JOIN saas_community_build scb ON h.building_num = scb.id\n" +
                    "\tLEFT JOIN saas_community_build_unit scbu ON h.unit = scbu.id\n" +
                    "\tLEFT JOIN m_match_user_house muh ON hrm.house_id = muh.house_id \n" +
                    "WHERE\n" +
                    "\t1 = 1 and h.id is not null ";

            StringBuilder where = new StringBuilder();
            List<Object> age = new ArrayList<>();


            // 登录类型
            Integer loginType = token.getLoginType();
            String userId = token.getId();
            Long orgId = token.getEnterpriseId();

            // 用户对应房屋
            List<Map<String, Object>> communityList = appCommunityService.findCommunity(accessToken).getResultData();

            if (loginType == 1) {// 企业用户
                // 企业用户拼接小区id
                if (communityList != null && !communityList.isEmpty()) {
                    StringBuilder communityIds = new StringBuilder("");
                    for (Map<String, Object> map : communityList) {
                        communityIds.append("'" + map.get("communityId") + "'").append(",");
                    }
                    String communityIdsStr = communityIds.toString().substring(0, communityIds.toString().lastIndexOf(","));

                    sql += "  AND h.residence_community_id IN (  " + communityIdsStr + " )  ";
                } else {
                    sql += "  AND h.residence_community_id IN ( null )  ";
                }
            } else {// 非企业用户
                // 登录用户名下房屋
                List<String> houseIdList = communityService.getHouseIdList(userId);
                if (houseIdList.isEmpty()) {
                    return ResultBean.successfulResult(apiData);
                }

                // 查名下管理房屋的成员
                StringBuilder houseIds = new StringBuilder("");
                for (String hId : houseIdList) {
                    houseIds.append("'" + hId + "'").append(",");
                }
                String houseIdsStr = houseIds.toString().substring(0, houseIds.toString().lastIndexOf(","));
                sql += "  and h.residence_community_id IN (  " + houseIdsStr + " )  ";
            }


            // 条件查询
            if (!StringUtils.isEmpty(residenceCommunityId)) {
                where.append(" and  h.residence_community_id = ? ");
                age.add(residenceCommunityId);
            }
            if (!StringUtils.isEmpty(roomNumber)) {
                where.append(" and  h.room_number = ? ");
                age.add(roomNumber);
            }

            if (buildingNum != null) {
                where.append(" and h.building_num = ? ");
                age.add(buildingNum);
            }

            if (unit != null) {
                where.append(" and h.unit = ? ");
                age.add(unit);
            }

            if (!StringUtils.isEmpty(name)) {
                where.append(" and  hrm.match_user_name  like '%").append(name).append("%' ");
            }

            if (paymentStatus != null) {
                where.append(" and  hrm.payment_status  = ? ");
                age.add(paymentStatus);
            }
            if (type != null) {
                where.append(" and  hrm.type  = ? ");
                age.add(type);
            }
            where.append(" and  hrm.org_id  = ? ");
            age.add(orgId);
            // 查询总记录数
            String count = "select count(1) FROM (" + sql + where + ") c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, age.toArray());
            if (total == 0) {
                apiData.setData(data);
                apiData.setTotal(total);
                return ResultBean.successfulResult(apiData);
            }

            age.add(pageSize);
            age.add(pageNumber * pageSize);

            where.append(" ORDER BY  hrm.create_time  desc ");

            data = jdbcTemplate.query(sql + where + SQL_PAGE, new BeanPropertyRowMapper<>(RetiredVo.class), age.toArray());

            // 查询操作人名称
            List<String> operatorIds = data.stream().map(RetiredVo::getOperatorId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            if (!operatorIds.isEmpty()) {
                List<User> userS = userRepository.findByIdIn(operatorIds);
                for (User user : userS) {
                    for (RetiredVo vo : data) {
                        if (vo.getOperatorId().equals(user.getId())) {
                            vo.setOperatorName(user.getName());
                        }
                    }
                }
            }
            data.forEach(v -> {
                v.setCost(ConvertUtils.fenToYuan(v.getCost()));
                v.setOtherCost(ConvertUtils.fenToYuan(v.getOtherCost()));
                if (StrUtil.isEmpty(v.getMatchUserName()) && StrUtil.isNotEmpty(v.getMatchUserId())) {
                    List<MatchUser> matchUserList = matchUserRepository.findByUserId(v.getMatchUserId());
                    if (CollectionUtil.isNotEmpty(matchUserList)) {
                        v.setMatchUserName(matchUserList.get(0).getName());
                    }
                }
            });

            apiData.setData(data);
            apiData.setTotal(total);
            return ResultBean.successfulResult(apiData);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 退费记录-详情
     *
     * @return
     */
    public ResultBean<ReturnDetailsVo> returnParticulars(String accessToken, Long returnId) {
        log.info("AccountManageService returnParticulars accessToken={},returnId={}", accessToken, returnId);
        try {
            ReturnDetailsVo vo = new ReturnDetailsVo();

            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }
            if (returnId == null) {
                return ResultBean.failedResultOfParamWithMsg("退租id为空");
            }
            Optional<HouseReturnPremium> premium = houseReturnPremiumRepository.findById(returnId);
            if (!premium.isPresent()) {
                return ResultBean.failedResultOfParamWithMsg("房屋退租信息未找到");
            }
            HouseReturnPremium returnPremium = premium.get();
            BeanUtils.copyProperties(vo, returnPremium);

            if (StringUtils.isNotBlank(returnPremium.getMatchUserId())) {
                Optional<AppUser> byId = appUserRepository.findById(returnPremium.getMatchUserId());
                if (byId.isPresent()) {
                    String phone = byId.get().getPhone();
                    vo.setMatchUserPhone(phone);
                } else {
                    List<CommunityHouseUser> byUserId = communityHouseUserRepository.findByUserId(returnPremium.getMatchUserId());
                    if (!byUserId.isEmpty()) {
                        String mobile = byUserId.get(0).getMobile();
                        vo.setMatchUserPhone(mobile);
                    }
                }
                if (StringUtils.isBlank(vo.getMatchUserPhone())) {
                    String matchUserId = returnPremium.getMatchUserId();
                    User user = userRepository.findById(matchUserId);
                    if (user != null) {
                        vo.setMatchUserPhone(user.getMobile());
                    }
                }
            }
            // 账户余额明细
            Long remId = returnPremium.getRemainingId();
            if (remId != null) {
                Optional<HouseRemaining> rem = houseRemainingRepository.findById(remId);
                HouseRemaining remaining = rem.get();
                vo.setRemainingCost(ConvertUtils.fenConvertYuan(remaining.getBalanceFee()));
                vo.setCashPledge(ConvertUtils.fenConvertYuan(remaining.getCashPledge()));
            }

            List<BillVO> billVOS = new ArrayList<>();
            // 账单明细
            Integer totalBillCost = 0;
            List<HouseReturnBillRelation> returnBillRelations = houseReturnBillRelationRepository.findByReturnId(returnId);
            if (!returnBillRelations.isEmpty()) {
                for (HouseReturnBillRelation relation : returnBillRelations) {
                    BillVO billVO = new BillVO();
                    // 新增账单明细
                    switch (relation.getBillType()) {
                        // 1水费 2电费 3物业费 4宽带费 5电视费 6煤气费 7暖气费 8租金 9押金
                        case 1:
                        case 2:
                        case 3:
                        case 4:
                        case 5:
                        case 6:
                        case 7:
                            Optional<EstateExpenseBill> expenseBill = estateExpenseBillRepository.findById(relation.getBillId());
                            if (expenseBill.isPresent()) {
                                EstateExpenseBill estateExpenseBill = expenseBill.get();
                                billVO.setChargeType(relation.getBillType());
                                billVO.setCost(ConvertUtils.fen2yuan(estateExpenseBill.getSurplusCost()));
                                billVO.setStartTime(estateExpenseBill.getStartTime().toString());
                                billVO.setEndTime(estateExpenseBill.getEndTime().toString());
                                billVO.setId(estateExpenseBill.getId());
                                billVO.setOrgId(estateExpenseBill.getOrgId());
                                totalBillCost += estateExpenseBill.getSurplusCost();
                            }
                            break;
                        case 8:
                        case 9:
                            Optional<EstateRentBill> estateRentBill = estateRentBillRepository.findById(relation.getBillId());
                            if (estateRentBill.isPresent()) {
                                EstateRentBill rentBill = estateRentBill.get();
                                billVO.setChargeType(relation.getBillType());
                                billVO.setCost(ConvertUtils.fen2yuan(rentBill.getSurplusCost()));
                                billVO.setStartTime(rentBill.getStartTime().toString());
                                billVO.setEndTime(rentBill.getEndTime().toString());
                                billVO.setId(rentBill.getId());
                                billVO.setOrgId(rentBill.getOrgId());
                                totalBillCost += rentBill.getSurplusCost();
                            }
                            break;
                    }
                    billVOS.add(billVO);
                }
            }
            vo.setBillVOS(billVOS);
            vo.setTotalBillCost(ConvertUtils.fenConvertYuan(totalBillCost));
            vo.setCost(ConvertUtils.fenToYuan(vo.getCost()));
            vo.setViolateCost(ConvertUtils.fenToYuan(vo.getViolateCost()));


            return ResultBean.successfulResult(vo);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 数据记录-延期记录-取消延期
     *
     * @return
     */
    @Transactional
    public ResultBean<Object> cancelPostpone(String accessToken, Long remainingId, String cause, Long postponeId) {
        try {
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }
            String userId = token.getId();
            Date date = new Date();
            if (remainingId == null || postponeId == null)
                return ResultBean.failedResultOfParamWithMsg("参数有误");

            Optional<HouseRemaining> byId = houseRemainingRepository.findById(remainingId);
            if (!byId.isPresent()) {
                return ResultBean.failedResultWithMsg("账户不存在");
            }
            if (StringUtils.isBlank(cause)) {
                return ResultBean.failedResultWithMsg("请填写取消原因！");
            }

            Optional<HouseRemainingPostpone> byId1 = houseRemainingPostponeRepository.findById(postponeId);
            if (!byId1.isPresent()) {
                return ResultBean.failedResultWithMsg("当前记录未找到！");
            }

            HouseRemainingPostpone houseRemainingPostpone = byId1.get();
            houseRemainingPostpone.setCancelStatus(1);

            HouseRemaining remaining = byId.get();
            Integer status = remaining.getStatus();
            if (status == null || status != RemainingStatusEnum.POSTPONE.getValue()) {
                return ResultBean.failedResultWithMsg("当前账户非延期状态");
            }

            // shouldPayTime
//            expenseBillList.stream().

            DepartmentBill departmentBill = departmentBillRepository.findByDepId(remaining.getOrgId());
            DateTime nowTime = DateUtil.date();


            //
            boolean lockResult = false;
            // 1水费 2电费 3物业费 4宽带费 5电视费 6煤气费 7暖气费 8租金  9押金 10退租
            Integer billStatus = departmentBill.getSmartLockStatus();
            if (billStatus != null) {
                switch (billStatus) {
                    // 1水费
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                        // bug 1694，取消延期失败
                        // List<EstateExpenseBill> expenseBillList = estateExpenseBillRepository.findByAuditStatusAndPaymentStatusAndHouseIdAndOrgId(1, 0, remaining.getHouseId(), remaining.getOrgId());
                        List<EstateExpenseBill> expenseBillList = estateExpenseBillRepository.findByPaymentStatusAndHouseIdAndOrgId(0, remaining.getHouseId(), remaining.getOrgId());
                        // 判断集合对象中的时间字段是否超过当前时间
                        lockResult = expenseBillList.stream().anyMatch(x -> x.getShouldPayTime().before(nowTime));
                        break;
                    case 8:// 1租金
                    case 9:// 2押金
                        // List<EstateRentBill> billList = estateRentBillRepository.findByAuditStatusAndPaymentStatusAndHouseIdAndOrgId(1, 0, remaining.getHouseId(), remaining.getOrgId());
                        List<EstateRentBill> billList = estateRentBillRepository.findByPaymentStatusAndHouseIdAndOrgId(0, remaining.getHouseId(), remaining.getOrgId());
                        // 判断集合对象中的时间字段是否超过当前时间
                        lockResult = billList.stream().anyMatch(x -> x.getShouldPayTime().before(nowTime));
                        break;
                    case 10:
                        break;
                }
            }

            remaining.setDeferredEndTime(date);
            if (lockResult) {
                remaining.setStatus(7);
            }

            HouseRemainingPostpone postpone = new HouseRemainingPostpone();
            postpone.setRemainingId(remainingId);
            postpone.setPostponeType(1);
            postpone.setOperatorId(userId);
            postpone.setLastUpdateTime(date);
            postpone.setCause(cause);
            postpone.setDeferredStartTime(remaining.getDeferredStartTime());
            postpone.setDeferredEndTime(date);
            postpone.setPostponeId(postponeId);

            // 账户欠费冻结锁
            if (lockResult) {
                lockAppService.cancelpostpone(accessToken, remaining.getHouseId(), cause);
            }

            houseRemainingRepository.save(remaining);
            houseRemainingPostponeRepository.save(postpone);
            houseRemainingPostponeRepository.save(houseRemainingPostpone);
            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }


    /**
     * 延期记录-取消延期-详情
     *
     * @param accessToken
     * @param postponeId
     * @return
     */
    public ResultBean<PostponeVo> postponeParticulars(String accessToken, Long postponeId) {
        try {
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }
            PostponeVo vo = new PostponeVo();

            if (postponeId == null)
                return ResultBean.failedResultOfParamWithMsg("参数有误");

            Optional<HouseRemainingPostpone> postponeByid = houseRemainingPostponeRepository.findById(postponeId);
            if (!postponeByid.isPresent()) {
                return ResultBean.failedResultWithMsg("当前记录未找到！");
            }

            HouseRemainingPostpone postpone = postponeByid.get();
            vo = ObjectConversion.copy(postpone, PostponeVo.class);


            // 查询操作人名称

            if (StringUtils.isNotBlank(vo.getOperatorId())) {
                User user = userRepository.findById(vo.getOperatorId());
                if (user != null) {
                    if (vo.getOperatorId().equals(user.getId())) {
                        vo.setOperatorName(user.getName());
                    }
                }
            }


            return ResultBean.successfulResult(vo);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 账户管理-单位账户缴费详情
     */
    public ResultBean<PaymentOrderApiData<DepRemainingRecordVo>> depRemainingPay(String accessToken, Integer pageNumber, Integer pageSize, Long remainingId) {
        try {
            TokenRedisVo token = redisService.findTokenVo(accessToken);
            if (token == null) {
                return ResultBean.failedResultOfToken();
            }

            if (remainingId == null) {
                return ResultBean.failedResultOfParamWithMsg("参数有误");
            }
            PaymentOrderApiData<DepRemainingRecordVo> apiData = new PaymentOrderApiData<>();
            List<DepRemainingRecordVo> data = new ArrayList<>();
            apiData.setData(data);
            apiData.setTotal(0L);
            apiData.setTotalAmount("0");

            String userId = token.getId();
            Long orgId = token.getEnterpriseId();

            int totalAmount = 0;
            List<HouseOfflinePaymentDetails> details = houseOfflinePaymentDetailsRepository.findByRemainingIdAndStatusAndAccountType(remainingId, 1, 1);
            if (!details.isEmpty()) {
                for (HouseOfflinePaymentDetails detail : details) {
                    DepRemainingRecordVo vo = new DepRemainingRecordVo();

                    User user = userRepository.findById(detail.getCreateUserId());
                    if (user != null) {
                        vo.setOperatorName(user.getName());
                    }
                    vo.setRemainingId(remainingId);
                    vo.setOperateMoney(ConvertUtils.fenConvertYuan(detail.getOperateMoney()));
                    vo.setOperatorId(detail.getCreateUserId());
                    vo.setUpdateTime(detail.getCreateTime());
                    vo.setStatus(1);
                    vo.setPaymentType(1);

                    totalAmount += detail.getOperateMoney();
                    data.add(vo);
                }
            }

            data = data.stream().sorted(Comparator.comparing(DepRemainingRecordVo::getUpdateTime).reversed()).collect(Collectors.toList());
            apiData.setTotal((long) data.size());
            apiData.setData(data);
            apiData.setTotalAmount(ConvertUtils.fenConvertYuan(totalAmount));
            return ResultBean.successfulResult(apiData);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    public static void main(String[] args) {
        String datetime = "2023-01-15 14:30:00";
// 将指定时间转换为DateTime类型
        DateTime dateTime = DateUtil.parse(datetime);

        int month = dateTime.month();
// 获取指定时间所在季度的月份
        int quarter = ((month - 1) / 3) + 2;
// 构造季度最小时间的字符串
        String quarterStartStr = StrUtil.format("{}-{}-01 00:00:00", dateTime.year(), ((quarter - 1) * 3) + 1);
// 将季度最小时间字符串转换为DateTime类型
        DateTime quarterStart = DateUtil.parse(quarterStartStr);
        System.out.println(quarterStart);

    }
}
